約 4,534,760 件
https://w.atwiki.jp/yosilove/pages/21.html
複数の音源を鳴らす-CPP ALUT CPP Mac OpenAL ソースコード 解説 最終更新日 2009-09-25 View - link_pdfプラグインはご利用いただけなくなりました。 ダウンロード View - OpenALで複数の音源がランダムな位置で鳴るサンプル。 ALUTが必要です。 ドップラー効果(Doppler Effect)-CPP main.cpp keyboard.cpp keyboad.h MakefileMac 実行方法 実行結果 メモ テスト環境 Tanks main.cpp #include stdlib.h #include math.h #include OpenAL/al.h #include OpenAL/alc.h #include AL/alut.h #include "keyboard.h" // Maximum data buffers we will need. #define NUM_BUFFERS 3 // Maximum emissions we will need. #define NUM_SOURCES 3 // These index the buffers and sources. #define BATTLE 0 #define GUN1 1 #define GUN2 2 // Buffers hold sound data. ALuint Buffers[NUM_BUFFERS]; // Sources are points of emitting sound. ALuint Sources[NUM_SOURCES]; // Position of the source sounds. ALfloat SourcesPos[NUM_SOURCES][3]; // Velocity of the source sounds. ALfloat SourcesVel[NUM_SOURCES][3]; // Position of the listener. ALfloat ListenerPos[] = { 0.0, 0.0, 0.0 }; // Velocity of the listener. ALfloat ListenerVel[] = { 0.0, 0.0, 0.0 }; // Orientation of the listener. (first 3 elements are "at", second 3 are "up") ALfloat ListenerOri[] = { 0.0, 0.0, -1.0, 0.0, 1.0, 0.0 }; /* * ALboolean LoadALData() * *This function will load our sample data from the disk using the alut *utility and send the data into OpenAL as a buffer. A source is then *also created to play that buffer. */ ALboolean LoadALData() { // Variables to load into. ALenum format; ALsizei size; ALvoid* data; ALsizei freq; ALboolean loop; // Load wav data into buffers. alGenBuffers(NUM_BUFFERS, Buffers); if(alGetError() != AL_NO_ERROR) return AL_FALSE; //wavファイルの読み込み(バッファの用意) alutLoadWAVFile((ALbyte*)"wavdata/Battle.wav", format, data, size, freq); alBufferData(Buffers[BATTLE], format, data, size, freq); alutUnloadWAV(format, data, size, freq); alutLoadWAVFile((ALbyte*)"wavdata/Gun1.wav", format, data, size, freq); alBufferData(Buffers[GUN1], format, data, size, freq); alutUnloadWAV(format, data, size, freq); alutLoadWAVFile((ALbyte*)"wavdata/Gun2.wav", format, data, size, freq); alBufferData(Buffers[GUN2], format, data, size, freq); alutUnloadWAV(format, data, size, freq); // Bind buffers into audio sources. alGenSources(NUM_SOURCES, Sources); if(alGetError() != AL_NO_ERROR) return AL_FALSE; //音源の設定 alSourcei (Sources[BATTLE], AL_BUFFER, Buffers[BATTLE] ); alSourcef (Sources[BATTLE], AL_PITCH, 1.0f ); alSourcef (Sources[BATTLE], AL_GAIN, 1.0f ); alSourcefv(Sources[BATTLE], AL_POSITION, SourcesPos[BATTLE]); alSourcefv(Sources[BATTLE], AL_VELOCITY, SourcesVel[BATTLE]); alSourcei (Sources[BATTLE], AL_LOOPING, AL_TRUE ); alSourcei (Sources[GUN1], AL_BUFFER, Buffers[GUN1] ); alSourcef (Sources[GUN1], AL_PITCH, 1.0f ); alSourcef (Sources[GUN1], AL_GAIN, 1.0f ); alSourcefv(Sources[GUN1], AL_POSITION, SourcesPos[GUN1]); alSourcefv(Sources[GUN1], AL_VELOCITY, SourcesVel[GUN1]); alSourcei (Sources[GUN1], AL_LOOPING, AL_FALSE ); alSourcei (Sources[GUN2], AL_BUFFER, Buffers[GUN2] ); alSourcef (Sources[GUN2], AL_PITCH, 1.0f ); alSourcef (Sources[GUN2], AL_GAIN, 1.0f ); alSourcefv(Sources[GUN2], AL_POSITION, SourcesPos[GUN2]); alSourcefv(Sources[GUN2], AL_VELOCITY, SourcesVel[GUN2]); alSourcei (Sources[GUN2], AL_LOOPING, AL_FALSE ); // Do another error check and return. if(alGetError() != AL_NO_ERROR) return AL_FALSE; return AL_TRUE; } /* * void SetListenerValues() * *We already defined certain values for the listener, but we need *to tell OpenAL to use that data. This function does just that. * 観測者の設定 */ void SetListenerValues() { alListenerfv(AL_POSITION, ListenerPos); alListenerfv(AL_VELOCITY, ListenerVel); alListenerfv(AL_ORIENTATION, ListenerOri); } /* * void KillALData() * *We have allocated memory for our buffers and sources which needs *to be returned to the system. This function frees that memory. * お掃除 */ void KillALData() { alDeleteBuffers(NUM_BUFFERS, Buffers); alDeleteSources(NUM_SOURCES, Sources); alutExit(); } int main(int argc, char *argv[]) { printf("MindCode s OpenAL Lesson 3 Multiple Sources \n\n"); printf("(Press any key to quit.) \n"); // Initialize OpenAL and clear the error bit. alutInit(NULL, 0); alGetError(); //音源の設定 if(LoadALData() == AL_FALSE) return 0; //観測者の設定 SetListenerValues(); // Setup an exit procedure. //終了時に呼び出す関数 atexit(KillALData); // Begin the battle sample to play. alSourcePlay(Sources[BATTLE]); // Go through all the sources and check that they are playing. // Skip the first source because it is looping anyway (will always be playing). ALint state; while(!kbhit()) { for(int i = 1; i NUM_SOURCES; i++) { alGetSourcei(Sources[i], AL_SOURCE_STATE, state); if(state != AL_PLAYING)//再生中でなければ { // Pick a random position around the listener to play the source. //ランダムな位置に移動 double theta = (double) (rand() % 360) * 3.14 / 180.0; SourcesPos[i][0] = -float(cos(theta)); SourcesPos[i][1] = -float(rand()%2); SourcesPos[i][2] = -float(sin(theta)); alSourcefv(Sources[i], AL_POSITION, SourcesPos[i]); //鳴らす alSourcePlay(Sources[i]); } } } return 0; } keyboard.cpp /* This is the unix code for kbhit I found on google at http //www.linuxquestions.org/questions/archive/9/2002/10/4/34027 */ #include "keyboard.h" void init_keyboard() { tcgetattr(0, initial_settings); new_settings = initial_settings; new_settings.c_lflag = ~ICANON; new_settings.c_lflag = ~ECHO; new_settings.c_lflag = ~ISIG; new_settings.c_cc[VMIN] = 1; new_settings.c_cc[VTIME] = 0; tcsetattr(0, TCSANOW, new_settings); } void close_keyboard() { tcsetattr(0, TCSANOW, initial_settings); } int kbhit() { char ch; int nread; if(peek_character != -1) return 1; new_settings.c_cc[VMIN]=0; tcsetattr(0, TCSANOW, new_settings); nread = read(0, ch,1); new_settings.c_cc[VMIN]=1; tcsetattr(0, TCSANOW, new_settings); if(nread == 1) { peek_character = ch; return 1; } return 0; } int readch() { char ch; if(peek_character != -1) { ch = peek_character; peek_character = -1; return ch; } read(0, ch,1); return ch; } keyboad.h /* This is the unix code for kbhit I found on google at http //www.linuxquestions.org/questions/archive/9/2002/10/4/34027 */ #include stdio.h #include termios.h #include term.h #include curses.h #include unistd.h static struct termios initial_settings, new_settings; static int peek_character = -1; void init_keyboard(); void close_keyboard(); int kbhit(); int readch(); Makefile Mac CC = g++ TARGET = lesson2 COMPILEFLAGS = -framework OpenAL -lalut $(TARGET) main.o keyboard.o $(CC) -o $(TARGET) main.o keyboard.o $(COMPILEFLAGS) main.o main.cpp $(CC) -c main.cpp -Wno-deprecated keyboard.o keyboard.h keyboard.cpp $(CC) -c keyboard.cpp -Wno-deprecated clean rm -f $(TARGET) main.o 実行方法 コンパイルして make 実行 ./lesson3 実行結果 Multi.mp3 メモ makeすると以下のようなメッセージが出たりするかもしれません。 main.cpp 66 warning ‘alutLoadWAVFile’ is deprecated (declared at /usr/local/include/AL/alut.h 110) これは「alutLoadWAVFile」は今後のバージョンアップで使えなくなるかもよというメッセージです。 ALUTがバージョンアップすると、この関数は別の関数で置き換える必要がでるかも知れないので注意! テスト環境 MacOSX 10.5.8 i686-apple-darwin9-g++-4.0.1 (GCC) 4.0.1 OpenAL ALUT 1.1.0 Tanks OpenAL Lesson 3 Multiple Sources
https://w.atwiki.jp/intensity/pages/28.html
//----------------------------------------------------------------------------- // $Id DecklinkCapture.cpp,v 1.2 2006/04/11 01 11 07 ivanr Exp $ // // Desc DirectShow capture sample // // Copyright (c) Blackmagic Design 2005. All rights reserved. //----------------------------------------------------------------------------- #include "stdafx.h" #include "DecklinkCapture.h" #include "DecklinkCaptureDlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif // CDecklinkCaptureApp BEGIN_MESSAGE_MAP(CDecklinkCaptureApp, CWinApp) ON_COMMAND(ID_HELP, CWinApp OnHelp) END_MESSAGE_MAP() // CDecklinkCaptureApp construction CDecklinkCaptureApp CDecklinkCaptureApp() { // TODO add construction code here, // Place all significant initialization in InitInstance } // The one and only CDecklinkCaptureApp object CDecklinkCaptureApp theApp; // CDecklinkCaptureApp initialization BOOL CDecklinkCaptureApp InitInstance() { // InitCommonControls() is required on Windows XP if an application // manifest specifies use of ComCtl32.dll version 6 or later to enable // visual styles. Otherwise, any window creation will fail. InitCommonControls(); CWinApp InitInstance(); AfxEnableControlContainer(); CoInitialize(NULL); // Standard initialization // If you are not using these features and wish to reduce the size // of your final executable, you should remove from the following // the specific initialization routines you do not need // Change the registry key under which our settings are stored // TODO You should modify this string to be something appropriate // such as the name of your company or organization SetRegistryKey(_T("Local AppWizard-Generated Applications")); CDecklinkCaptureDlg dlg; m_pMainWnd = dlg; INT_PTR nResponse = dlg.DoModal(); if (nResponse == IDOK) { // TODO Place code here to handle when the dialog is // dismissed with OK } else if (nResponse == IDCANCEL) { // TODO Place code here to handle when the dialog is // dismissed with Cancel } CoUninitialize(); // Since the dialog has been closed, return FALSE so that we exit the // application, rather than start the application s message pump. return FALSE; }
https://w.atwiki.jp/intensity/pages/29.html
//----------------------------------------------------------------------------- // $Id DecklinkCaptureDlg.cpp,v 1.9 2006/04/11 01 11 07 ivanr Exp $ // // Desc DirectShow capture sample // // Copyright (c) Blackmagic Design 2005. All rights reserved. //----------------------------------------------------------------------------- #include "stdafx.h" #include "DecklinkCapture.h" #include "DecklinkCaptureDlg.h" #include initguid.h // TODO move this to a lib #include "DecklinkSample_uuids.h" #undef lstrlenW #ifdef _DEBUG #define new DEBUG_NEW #endif #define WM_GRAPHNOTIFYWM_APP+1// for Filter Graph event notification //----------------------------------------------------------------------------- // CAboutDlg //----------------------------------------------------------------------------- // CAboutDlg dialog used for App About class CAboutDlg public CDialog { public CAboutDlg(); // Dialog Data enum { IDD = IDD_ABOUTBOX }; protected virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected DECLARE_MESSAGE_MAP() }; CAboutDlg CAboutDlg() CDialog(CAboutDlg IDD) { } void CAboutDlg DoDataExchange(CDataExchange* pDX) { CDialog DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() //----------------------------------------------------------------------------- // CDecklinkCaptureDlg dialog //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Constructor // CDecklinkCaptureDlg CDecklinkCaptureDlg(CWnd* pParent /*=NULL*/) CDialog(CDecklinkCaptureDlg IDD, pParent) , m_pIVW(NULL) { m_hIcon = AfxGetApp()- LoadIcon(IDR_MAINFRAME); } //----------------------------------------------------------------------------- // DoDataExchange // void CDecklinkCaptureDlg DoDataExchange(CDataExchange* pDX) { CDialog DoDataExchange(pDX); DDX_Control(pDX, IDC_COMBO_VIDEOFORMATS, m_videoFormatCtrl); DDX_Control(pDX, IDC_COMBO_AUDIOFORMATS, m_audioFormatCtrl); DDX_Control(pDX, IDC_STATIC_PREVIEW, m_preview); DDX_Control(pDX, IDC_EDIT_CAPTUREFILE, m_captureFileCtrl); DDX_Control(pDX, IDC_COMBO_COMPRESSION, m_compressionCtrl); DDX_Control(pDX, IDC_COMBO_VIDEODEVICE, m_videoDeviceCtrl); DDX_Control(pDX, IDC_COMBO_AUDIODEVICE, m_audioDeviceCtrl); } BEGIN_MESSAGE_MAP(CDecklinkCaptureDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_CBN_SELCHANGE(IDC_COMBO_VIDEOFORMATS, OnCbnSelchangeComboVideoformats) ON_CBN_SELCHANGE(IDC_COMBO_AUDIOFORMATS, OnCbnSelchangeComboAudioformats) ON_BN_CLICKED(IDC_CHECK_AUDIOMUTE, OnBnClickedCheckAudiomute) ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnBnClickedButtonBrowse) ON_BN_CLICKED(IDC_BUTTON_CAPTURE, OnBnClickedButtonCapture) ON_BN_CLICKED(IDC_BUTTON_STOP, OnBnClickedButtonStop) ON_CBN_SELCHANGE(IDC_COMBO_COMPRESSION, OnCbnSelchangeComboCompression) ON_CBN_SELCHANGE(IDC_COMBO_VIDEODEVICE, OnCbnSelchangeComboVideodevice) ON_CBN_SELCHANGE(IDC_COMBO_AUDIODEVICE, OnCbnSelchangeComboAudiodevice) END_MESSAGE_MAP() //----------------------------------------------------------------------------- // CDecklinkCaptureDlg message handlers //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // OnInitDialog // Called before the dialog is displayed, use this message handler to initialise // our app BOOL CDecklinkCaptureDlg OnInitDialog() { CDialog OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu- AppendMenu(MF_SEPARATOR); pSysMenu- AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application s main window is not a dialog SetIcon(m_hIcon, TRUE);// Set big icon SetIcon(m_hIcon, FALSE);// Set small icon // create a basic capture graph and preview the incoming video m_pGraph = NULL; m_pVideoCapture = NULL; m_pAudioCapture = NULL; m_pVideoRenderer = NULL; m_pSmartT = NULL; m_pControl = NULL; m_pIVW = NULL; m_pMediaEvent = NULL; m_ROTRegister = 0; m_bAudioMute = FALSE; m_compressor = 0; m_bEnableCompressionCtrl = TRUE; m_captureFile = " Select File "; // initialise default video media type ZeroMemory( m_vihDefault, sizeof(m_vihDefault)); m_vihDefault.AvgTimePerFrame = 333667; m_vihDefault.bmiHeader.biWidth = 720; m_vihDefault.bmiHeader.biHeight = 486; m_vihDefault.bmiHeader.biBitCount = 16; m_vihDefault.bmiHeader.biCompression = YVYU ; // initialise default audio media type ZeroMemory( m_wfexDefault, sizeof(m_wfexDefault)); m_wfexDefault.nChannels = 2;// the only field of interest // retrieve last state QueryRegistry(); m_captureFileCtrl.SetWindowText(m_captureFile); EnableControls(); // create a preview graph // add the filters that will be used by all the graphs; preview, uncompressed capture, dv capture, // mpeg capture and windows media capture HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, reinterpret_cast void** ( m_pGraph)); if (SUCCEEDED(hr)) { #ifdef _DEBUG hr = CDSUtils AddGraphToRot(m_pGraph, m_ROTRegister); #endif hr = m_pGraph- QueryInterface(IID_IMediaControl, reinterpret_cast void** ( m_pControl)); if (SUCCEEDED(hr)) { // locate the video capture devices hr = PopulateDeviceControl( CLSID_VideoInputDeviceCategory, m_videoDeviceCtrl); if (SUCCEEDED(hr)) { hr = PopulateDeviceControl( CLSID_AudioInputDeviceCategory, m_audioDeviceCtrl); if (SUCCEEDED(hr)) { PWSTR pVideoName = (PWSTR)m_videoDeviceCtrl.GetItemData(m_videoDeviceCtrl.SetCurSel(0)); PWSTR pAudioName = (PWSTR)m_audioDeviceCtrl.GetItemData(m_audioDeviceCtrl.SetCurSel(0)); if (pVideoName pAudioName) { hr = CDSUtils AddFilter2(m_pGraph, CLSID_VideoInputDeviceCategory, pVideoName, m_pVideoCapture); if (SUCCEEDED(hr)) { hr = CDSUtils AddFilter2(m_pGraph, CLSID_AudioInputDeviceCategory, pAudioName, m_pAudioCapture); if (SUCCEEDED(hr)) { PopulateVideoControl();// populate the video format control with the video formats of the currently selected device PopulateAudioControl();// populate the audio format control with the audio formats of the currently selected device PopulateCompressionControl(); // locate video screen renderer for the preview window hr = CDSUtils AddFilter(m_pGraph, CLSID_VideoRendererDefault, L"Video Renderer", m_pVideoRenderer); if (SUCCEEDED(hr)) { hr = CreatePreviewGraph(); } } } } } } } } return TRUE; // return TRUE unless you set the focus to a control } //----------------------------------------------------------------------------- // DestroyWindow // Called when the window is being destroyed, clean up and free all resources. BOOL CDecklinkCaptureDlg DestroyWindow() { m_regUtils.Close(); #ifdef _DEBUG CDSUtils RemoveGraphFromRot(m_ROTRegister); #endif DestroyGraph(); SAFE_RELEASE(m_pControl); // Hide Video Window and remove owner. This has to be done prior to // destroying any window that displays video/still. if (m_pIVW) { m_pIVW- put_Visible(OAFALSE); m_pIVW- put_Owner(NULL); } SAFE_RELEASE(m_pIVW); SAFE_RELEASE(m_pMediaEvent); SAFE_RELEASE(m_pVideoRenderer); SAFE_RELEASE(m_pAudioCapture); SAFE_RELEASE(m_pVideoCapture); SAFE_RELEASE(m_pGraph); // free mediatypes attached to format controls int count = m_videoFormatCtrl.GetCount(); for (int item=0; item count; ++item) { DeleteMediaType((AM_MEDIA_TYPE*)m_videoFormatCtrl.GetItemData(item)); } count = m_audioFormatCtrl.GetCount(); for (int item=0; item count; ++item) { DeleteMediaType((AM_MEDIA_TYPE*)m_audioFormatCtrl.GetItemData(item)); } // release the device names attached to the item s data count = m_videoDeviceCtrl.GetCount(); for (item=0; item count; ++item) { PWSTR pName = (PWSTR)m_videoDeviceCtrl.GetItemData(item); delete [] pName; } count = m_audioDeviceCtrl.GetCount(); for (item=0; item count; ++item) { PWSTR pName = (PWSTR)m_audioDeviceCtrl.GetItemData(item); delete [] pName; } return CDialog DestroyWindow(); } //----------------------------------------------------------------------------- // OnSysCommand // void CDecklinkCaptureDlg OnSysCommand(UINT nID, LPARAM lParam) { if ((nID 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog OnSysCommand(nID, lParam); } } //----------------------------------------------------------------------------- // OnPaint // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CDecklinkCaptureDlg OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast WPARAM (dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect( rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog OnPaint(); } } //----------------------------------------------------------------------------- // HandleGraphEvent // At the moment we just read the event, discard it and release memory used to store it. void CDecklinkCaptureDlg HandleGraphEvent(void) { LONG lEventCode, lEventParam1, lEventParam2; if (!m_pMediaEvent) { return; } while (SUCCEEDED(m_pMediaEvent- GetEvent( lEventCode, reinterpret_cast LONG_PTR * ( lEventParam1), reinterpret_cast LONG_PTR * ( lEventParam2), 0))) { // just free memory associated with event m_pMediaEvent- FreeEventParams(lEventCode, lEventParam1, lEventParam2); } } //----------------------------------------------------------------------------- // WindowProc // Have to add our own message handling loop to handle events from the preview video // window and to pass Window events onto it - this is so it redraws itself correctly etc. LRESULT CDecklinkCaptureDlg WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_GRAPHNOTIFY HandleGraphEvent(); break; } // Pass all msgs to video window. vid window exists as child of static // picture frame. This ensures video window redraws itself etc. if (m_pIVW) { m_pIVW- NotifyOwnerMessage(reinterpret_cast LONG_PTR (m_hWnd) /* from me */, message, wParam, lParam); } return CDialog WindowProc(message, wParam, lParam); } //----------------------------------------------------------------------------- // OnQueryDragIcon // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CDecklinkCaptureDlg OnQueryDragIcon() { return static_cast HCURSOR (m_hIcon); } //----------------------------------------------------------------------------- // CreatePreviewGraph // Create a graph to preview the input // NOTE There are many ways of building graphs, you could opt for the ICaptureGraphBuilder interface which would // make things are lot simpler, however it doesn t always build the most efficient graphs. HRESULT CDecklinkCaptureDlg CreatePreviewGraph() { HRESULT hr = S_OK; if (m_pGraph) { // locate smart-T // NOTE The smart-T appears to hold references to its upstream connections even when its input pin // is diconnected. The smart-T has to be removed from the graph in order to clear these references which // is why the filter is enumerated and added every time the preview graph is built and removed whenever // it is destroyed. ASSERT(NULL == m_pSmartT); hr = CDSUtils AddFilter(m_pGraph, CLSID_SmartTee, L"Smart Tee", m_pSmartT); if (SUCCEEDED(hr)) { // DV preview is slightly different to all other previews if (ENC_DV != m_compressionCtrl.GetItemData(m_compressionCtrl.GetCurSel())) { // uncompressed, mpeg and wm preview // create the following // // Decklink Video Capture - Smart-T - AVI Decompressor - Video Renderer // Decklink Audio Capture - Default Audio Renderer // // render the preview pin on the smart-T filter // first connect the Decklink video capture pin to the smart-T hr = CDSUtils ConnectFilters(m_pGraph, m_pVideoCapture, NULL, m_pSmartT, NULL); if (SUCCEEDED(hr)) { // now connect the preview pin of the smart-T to the video renderer hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, L"Preview", m_pVideoRenderer, NULL); } } else { // DV Preview // create the following // // Decklink Video Capture - AVI Decompressor - Smart-T - Colour Space Converter - Video Renderer // Decklink Audio Capture - Default Audio Renderer // // this is a more efficient graph than created by the ICaptureGraphBuilder2 interface // add the AVI decompressor and colour space converter filters CComPtr IBaseFilter pAVIDecompressor = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_AVIDec, L"AVI Decompressor", pAVIDecompressor); if (SUCCEEDED(hr)) { CComPtr IBaseFilter pColourSpaceConverter = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_Colour, L"Color Space Converter", pColourSpaceConverter); if (SUCCEEDED(hr)) { // conect the Decklink video capture pin to the AVI decompressor hr = CDSUtils ConnectFilters(m_pGraph, m_pVideoCapture, NULL, pAVIDecompressor, NULL); if (SUCCEEDED(hr)) { // connect AVI decompressor to the smart-T hr = CDSUtils ConnectFilters(m_pGraph, pAVIDecompressor, NULL, m_pSmartT, NULL); if (SUCCEEDED(hr)) { // connect the preview pin of the smart-T to the colour space converter hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, L"Preview", pColourSpaceConverter, NULL); if (SUCCEEDED(hr)) { // connect the colour space converter to the video renderer hr = CDSUtils ConnectFilters(m_pGraph, pColourSpaceConverter, NULL, m_pVideoRenderer, NULL); } } } } } } } } else { hr = E_POINTER; } if (SUCCEEDED(hr)) { // the video path has been connected, initialise the preview window InitialiseVideoPreview(); // optionally connect the audio path if (FALSE == m_bAudioMute) { // connect the Decklink audio capture pin to the mux hr = CDSUtils RenderFilter(m_pGraph, m_pAudioCapture, L"Capture"); } // run the graph so that we can preview the input video if (m_pControl) { hr = m_pControl- Run(); } else { hr = E_POINTER; } } return hr; } //----------------------------------------------------------------------------- // CreateCaptureGraph // Create a graph to capture the input HRESULT CDecklinkCaptureDlg CreateCaptureGraph() { HRESULT hr = S_OK; // tack the file writer onto the preview graph if (m_pGraph m_pControl) { // stop the graph as we are about to modify it m_pControl- Stop(); // remove the default audio renderer so the Decklink audio capture filter // can be connected to the AVI mux, we will not preview audio whilst capturing CComPtr IPin pIPinOutput = NULL; hr = CDSUtils GetPin(m_pAudioCapture, L"Capture", pIPinOutput); if (SUCCEEDED(hr)) { // to disconnect both pins must be disconnected // find the pin connected to the Decklink audio capture pin CComPtr IPin pIPinConnection = NULL; hr = pIPinOutput- ConnectedTo( pIPinConnection); if (SUCCEEDED(hr)) { // disconnect the pins hr = m_pGraph- Disconnect(pIPinOutput); hr = m_pGraph- Disconnect(pIPinConnection); // get the owning filter of the downstream pin and remove it from the graph PIN_INFO pinInfo = {0}; hr = pIPinConnection- QueryPinInfo( pinInfo); if (SUCCEEDED(hr)) { if (pinInfo.pFilter) { hr = m_pGraph- RemoveFilter(pinInfo.pFilter); pinInfo.pFilter- Release(); } } } } // retrieve the capture filename m_captureFileCtrl.GetWindowText(m_captureFile); // store filename USES_CONVERSION; WCHAR captureFile[MAX_PATH]; wcsncpy(captureFile, A2W(m_captureFile), MAX_PATH); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetString("CaptureFile", reinterpret_cast const BYTE* (captureFile), sizeof(captureFile))); // decide the type of capture graph to build switch (m_compressionCtrl.GetItemData(m_compressionCtrl.GetCurSel())) { default case ENC_NONE hr = CreateUncompressedCaptureGraph(); break; case ENC_DV hr = CreateDVCaptureGraph(); break; case ENC_WM hr = CreateWMCaptureGraph(); break; } if (FAILED(hr)) { // there was a problem building the capture graph, issue a message // and rebuild preview graph char buffer[128]; StringCbPrintfA(buffer, sizeof(buffer), "The error 0x%08lx was detected when creating the capture graph with the following file name \r\n\r\n %s ", hr, m_captureFile); MessageBox(buffer, _T("Error"), MB_ICONERROR); OnBnClickedButtonStop();// destroy broken capture graph, build preview graph and enable controls } } else { hr = E_POINTER; } return hr; } //----------------------------------------------------------------------------- // CreateUncompressedCaptureGraph // Create an optimum uncompressed capture graph HRESULT CDecklinkCaptureDlg CreateUncompressedCaptureGraph() { HRESULT hr = S_OK; // uncompressed capture // locate the AVI mux and file writer filters and add them to the graph CComPtr IBaseFilter pAVIMux = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_AviDest , L"AVI Mux", pAVIMux); if (SUCCEEDED(hr)) { CComPtr IBaseFilter pFileWriter = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_FileWriter, L"File writer", pFileWriter); if (SUCCEEDED(hr)) { // set the output filename CComQIPtr IFileSinkFilter, IID_IFileSinkFilter pIFS = pFileWriter; if (pIFS) { USES_CONVERSION;// for T2W macro hr = pIFS- SetFileName(T2W(m_captureFile), NULL); if (SUCCEEDED(hr)) { // connect the smart-T capture pin to the mux hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, L"Capture", pAVIMux, NULL); if (SUCCEEDED(hr)) { // connect the mux to the file writer hr = CDSUtils ConnectFilters(m_pGraph, pAVIMux, NULL, pFileWriter, NULL); if (SUCCEEDED(hr)) { // video path connected now optionally connect the audio path if (FALSE == m_bAudioMute) { // connect the Decklink audio capture pin to the mux hr = CDSUtils ConnectFilters(m_pGraph, m_pAudioCapture, L"Capture", pAVIMux, NULL); } if (SUCCEEDED(hr)) { m_pControl- Run(); } } } } } } } return hr; } //----------------------------------------------------------------------------- // CreateDVCaptureGraph // Create an optimum DV capture graph // NOTE that this will only work for SD HRESULT CDecklinkCaptureDlg CreateDVCaptureGraph() { HRESULT hr = S_OK; // locate the DV encoder, AVI mux and file writer filters and add them to the graph CComPtr IBaseFilter pDVEncoder = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_DVVideoEnc, L"DV Video Encoder", pDVEncoder); if (SUCCEEDED(hr)) { CComPtr IBaseFilter pAVIMux = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_AviDest , L"AVI Mux", pAVIMux); if (SUCCEEDED(hr)) { CComPtr IBaseFilter pFileWriter = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_FileWriter, L"File writer", pFileWriter); if (SUCCEEDED(hr)) { // set the output filename CComQIPtr IFileSinkFilter, IID_IFileSinkFilter pIFS = pFileWriter; if (pIFS) { USES_CONVERSION;// for T2W macro hr = pIFS- SetFileName(T2W(m_captureFile), NULL); if (SUCCEEDED(hr)) { // configure the DV encoder CComQIPtr IDVEnc, IID_IDVEnc pIDV = pDVEncoder; if (pIDV) { // located a DV compression filter, set the format int videoFormat, dvFormat, resolution; hr = pIDV- get_IFormatResolution( videoFormat, dvFormat, resolution, FALSE, NULL); if (SUCCEEDED(hr)) { ASSERT(DVENCODERFORMAT_DVSD == dvFormat); ASSERT(DVENCODERRESOLUTION_720x480 == resolution); if ((DVENCODERVIDEOFORMAT_NTSC == videoFormat) (576 == m_vihDefault.bmiHeader.biHeight)) { // set the encoder to PAL if its NTSC videoFormat = DVENCODERVIDEOFORMAT_PAL; hr = pIDV- put_IFormatResolution(videoFormat, dvFormat, resolution, FALSE, NULL); } else if ((DVENCODERVIDEOFORMAT_PAL == videoFormat) (486 == m_vihDefault.bmiHeader.biHeight)) { // set the encoder to NTSC if its PAL videoFormat = DVENCODERVIDEOFORMAT_NTSC; hr = pIDV- put_IFormatResolution(videoFormat, dvFormat, resolution, FALSE, NULL); } } } if (SUCCEEDED(hr)) { // if the format is PAL, insert the Decklink field swap filter, PAL DV is the opposite // field order to PAL SD if (576 == m_vihDefault.bmiHeader.biHeight) { CComPtr IBaseFilter pPALFieldSwap = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_DecklinkFieldSwap, L"Decklink PAL Field Swap", pPALFieldSwap); if (SUCCEEDED(hr)) { // connect the smart-T capture pin to the PAL field swap filter hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, L"Capture", pPALFieldSwap, NULL); if (SUCCEEDED(hr)) { // connect the field swap filter to the DV encoder hr = CDSUtils ConnectFilters(m_pGraph, pPALFieldSwap, NULL, pDVEncoder, NULL); } } } else { // connect the smart-T capture pin to the DV Encoder hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, L"Capture", pDVEncoder, NULL); } if (SUCCEEDED(hr)) { // connect the DV encoder output to the AVI mux hr = CDSUtils ConnectFilters(m_pGraph, pDVEncoder, NULL, pAVIMux, NULL); if (SUCCEEDED(hr)) { // connect the mux to the file writer hr = CDSUtils ConnectFilters(m_pGraph, pAVIMux, NULL, pFileWriter, NULL); if (SUCCEEDED(hr)) { // video path connected now optionally connect the audio path if (FALSE == m_bAudioMute) { // connect the Decklink audio capture pin to the mux hr = CDSUtils ConnectFilters(m_pGraph, m_pAudioCapture, L"Capture", pAVIMux, NULL); } if (SUCCEEDED(hr)) { m_pControl- Run(); } } } } } } } } } } return hr; } //----------------------------------------------------------------------------- // CreateWMCaptureGraph // Create an optimum Windows Media capture graph HRESULT CDecklinkCaptureDlg CreateWMCaptureGraph() { HRESULT hr = S_OK; // locate the asf writer filter and add it to the graph CComPtr IBaseFilter pASFWriter = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_WMAsfWriter, L"WM ASF Writer", pASFWriter); if (SUCCEEDED(hr)) { // set the output filename CComQIPtr IFileSinkFilter, IID_IFileSinkFilter pIFS = pASFWriter; if (pIFS) { USES_CONVERSION;// for T2W macro hr = pIFS- SetFileName(T2W(m_captureFile), NULL); if (SUCCEEDED(hr)) { hr = ConfigureWMEncoder(pASFWriter); } } if (SUCCEEDED(hr)) { if (FALSE == m_bAudioMute) { // connect the Decklink audio capture pin to the ASF writer hr = CDSUtils ConnectFilters(m_pGraph, m_pAudioCapture, pASFWriter, MEDIATYPE_Audio); } if (SUCCEEDED(hr)) { // connect the smart-T capture pin to the ASF writer hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, pASFWriter, MEDIATYPE_Video); if (SUCCEEDED(hr)) { m_pControl- Run(); } } } } return hr; } //----------------------------------------------------------------------------- // ConfigureWMEncoder // Configure the Windows Media encoder HRESULT CDecklinkCaptureDlg ConfigureWMEncoder(IBaseFilter* pASFWriter) { HRESULT hr = S_OK; // modify the video output resolution of a system profile if (pASFWriter) { // simple system profile encoding CComQIPtr IConfigAsfWriter, IID_IConfigAsfWriter pICW = pASFWriter; if (pICW) { //NOTE You could just use the following for a default system profile //hr = pICW- ConfigureFilterUsingProfileGuid(WMProfile_XXX);// RE wmsysprf.h //NOTE If you want video only capture you must modify the profile to remove the audio // otherwise encoding will fail // Load a system profile and modify the resolution of the video output // NOTE The scope of the encoding is enormous, this just demonstrates how to change // the output video resolution from 320x240 to something larger. // Changing the resolution affects coding performance, it is likely that the encoder will // start to drop frames after a while. Using WM9 codecs will probably improve performance // and that has been left to the reader... ;o) // // get a profile manager CComPtr IWMProfileManager pIWMProfileManager = NULL; hr = WMCreateProfileManager( pIWMProfileManager); if (SUCCEEDED(hr)) { // load a system profile to modify CComPtr IWMProfile pIWMProfile = NULL; // NOTE Any WMProfile_XXX could be used here, or create a custom profile from scratch hr = pIWMProfileManager- LoadProfileByID(WMProfile_V80_FAIRVBRVideo, pIWMProfile); if (SUCCEEDED(hr)) { // search the streams for the video stream and attempt to modify the video size DWORD cbStreams = 0; hr = pIWMProfile- GetStreamCount( cbStreams); if (SUCCEEDED(hr)) { IWMStreamConfig* pIWMStreamConfig = NULL; GUID streamType = {0}; DWORD stream; if (m_bAudioMute) { // remove the audio stream for video only capture for (stream=0; stream cbStreams; ++stream) { hr = pIWMProfile- GetStream(stream, pIWMStreamConfig); if (SUCCEEDED(hr)) { hr = pIWMStreamConfig- GetStreamType( streamType); if (SUCCEEDED(hr)) { if (MEDIATYPE_Audio == streamType) { if (SUCCEEDED(pIWMProfile- RemoveStream(pIWMStreamConfig))) { --cbStreams; } SAFE_RELEASE(pIWMStreamConfig); break; } } } } } for (stream=0; stream cbStreams; ++stream) { hr = pIWMProfile- GetStream(stream, pIWMStreamConfig); if (SUCCEEDED(hr)) { hr = pIWMStreamConfig- GetStreamType( streamType); if (SUCCEEDED(hr) (MEDIATYPE_Video == streamType)) { // found the video stream CComQIPtr IWMMediaProps, IID_IWMMediaProps pIWMMediaProps = pIWMStreamConfig; if (pIWMMediaProps) { // get the size of the media type WM_MEDIA_TYPE* pMediaType = NULL; DWORD cbMediaType = 0; hr = pIWMMediaProps- GetMediaType(pMediaType, cbMediaType); if (SUCCEEDED(hr)) { pMediaType = (WM_MEDIA_TYPE*)new char [cbMediaType]; if (pMediaType) { hr = pIWMMediaProps- GetMediaType(pMediaType, cbMediaType); if (SUCCEEDED(hr)) { BITMAPINFOHEADER* pbmih = NULL; if (WMFORMAT_VideoInfo == pMediaType- formattype) { WMVIDEOINFOHEADER* pvih = (WMVIDEOINFOHEADER*)pMediaType- pbFormat; pbmih = pvih- bmiHeader; } else if (WMFORMAT_MPEG2Video == pMediaType- formattype) { WMVIDEOINFOHEADER2* pvih = (WMVIDEOINFOHEADER2*) ((WMMPEG2VIDEOINFO*)pMediaType- pbFormat)- hdr; pbmih = pvih- bmiHeader; } if (pbmih) { // modify the video dimensions, set the property, reconfigure the stream // and then configure the ASF writer with this modified profile pbmih- biWidth = 640;// was 320; pbmih- biHeight = 480;// was 240; pbmih- biSizeImage = pbmih- biWidth * pbmih- biHeight * pbmih- biBitCount / 8;// NOTE This calculation is not correct for all bit depths hr = pIWMMediaProps- SetMediaType(pMediaType); if (SUCCEEDED(hr)) { // config the ASF writer filter to use this modified system profile hr = pIWMProfile- ReconfigStream(pIWMStreamConfig); if (SUCCEEDED(hr)) { hr = pICW- ConfigureFilterUsingProfile(pIWMProfile); } } } } delete [] (char*)pMediaType; } } } } SAFE_RELEASE(pIWMStreamConfig); } } } } } /* // modify other ASF writer properties IServiceProvider* pProvider = NULL; hr = pASFWriter- QueryInterface(IID_IServiceProvider, reinterpret_cast void** ( pProvider)); if (SUCCEEDED(hr)) { IID_IWMWriterAdvanced2* pWMWA2 = NULL; hr = pProvider- QueryService(IID_IID_IWMWriterAdvanced2, IID_IID_IWMWriterAdvanced2, reinterpret_cast void** ( pWMWA2)); if (SUCCEEDED(hr)) { // set the deinterlace mode pWMWA2- GetInputSetting(...); SAFE_RELEASE(pWMWA2); } SAFE_RELEASE(pProvider); } */ } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // DestroyGraph // Remove all intermediate filters, keep any Decklink and video render filters as // these are used by all the graphs. HRESULT CDecklinkCaptureDlg DestroyGraph() { HRESULT hr = S_OK; if (m_pGraph m_pControl) { m_pControl- Stop(); // release our outstanding reference on this filter so it can be removed from the graph SAFE_RELEASE(m_pSmartT); // retrieve the name of the capture device, don t remove it in this method PWSTR pNameVideoCapture = (PWSTR)m_videoDeviceCtrl.GetItemData(m_videoDeviceCtrl.GetCurSel()); PWSTR pNameAudioCapture = (PWSTR)m_audioDeviceCtrl.GetItemData(m_audioDeviceCtrl.GetCurSel()); CComPtr IEnumFilters pEnum = NULL; hr = m_pGraph- EnumFilters( pEnum); if (SUCCEEDED(hr)) { IBaseFilter* pFilter = NULL; while (S_OK == pEnum- Next(1, pFilter, NULL)) { FILTER_INFO filterInfo = {0}; hr = pFilter- QueryFilterInfo( filterInfo); if (SUCCEEDED(hr)) { SAFE_RELEASE(filterInfo.pGraph); if ((NULL == wcsstr(filterInfo.achName, pNameVideoCapture)) (NULL == wcsstr(filterInfo.achName, pNameAudioCapture)) (NULL == wcsstr(filterInfo.achName, L"Video Renderer"))) { hr = m_pGraph- RemoveFilter(pFilter); if (SUCCEEDED(hr)) { hr = pEnum- Reset(); } } } SAFE_RELEASE(pFilter); } } } else { hr = E_POINTER; } return hr; } //----------------------------------------------------------------------------- // InitialiseVideoPreview // In short get the video screen renderer to draw into the picture control, which is our preview window // the following code sets this up, in addition to adding the HandleGraphEvent and WindowProc methods // read the DXSDK docos for more detailed information void CDecklinkCaptureDlg InitialiseVideoPreview(void) { // modify the preview window if (m_pVideoRenderer) { if (NULL == m_pIVW) { if (SUCCEEDED(m_pVideoRenderer- QueryInterface(IID_IVideoWindow, reinterpret_cast void** ( m_pIVW)))) { // get the window to handle redraws, etc // Set msg drain of VideoWindow to point to our dialog window. The dialog s // window procedure then handles events from the VideoWindow. HRESULT hr = m_pIVW- put_MessageDrain(reinterpret_cast OAHWND (m_hWnd)); if (NULL == m_pMediaEvent) { // Make graph send WM_GRAPHNOTIFY when it wants our attention see "Learning // When an Event Occurs" in the DX9 documentation. hr = m_pGraph- QueryInterface(IID_IMediaEventEx, reinterpret_cast void** ( m_pMediaEvent)); if (SUCCEEDED(hr)) { hr = m_pMediaEvent- SetNotifyWindow(reinterpret_cast OAHWND (m_hWnd), WM_GRAPHNOTIFY, 0); } // object created for it. RECT rc; m_preview.GetClientRect( rc); m_pIVW- SetWindowPosition(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); // VideoWindow is a child window of the bounding rect hr = m_pIVW- put_WindowStyle(WS_CHILD); hr = m_pIVW- put_Owner(reinterpret_cast OAHWND (m_preview.GetSafeHwnd())); hr = m_pIVW- SetWindowForeground(-1); } } } } } //----------------------------------------------------------------------------- // PopulateDeviceControl // Fill device combo box with available devices of the specified category HRESULT CDecklinkCaptureDlg PopulateDeviceControl(const GUID* pCategory, CComboBox* pCtrl) { HRESULT hr = S_OK; if (pCategory pCtrl) { // first enumerate the system devices for the specifed class and filter name CComPtr ICreateDevEnum pSysDevEnum = NULL; hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast void** ( pSysDevEnum)); if (SUCCEEDED(hr)) { CComPtr IEnumMoniker pEnumCat = NULL; hr = pSysDevEnum- CreateClassEnumerator(*pCategory, pEnumCat, 0); if (S_OK == hr) { IMoniker* pMoniker = NULL; bool Loop = true; while ((S_OK == pEnumCat- Next(1, pMoniker, NULL)) Loop) { IPropertyBag* pPropBag = NULL; hr = pMoniker- BindToStorage(0, 0, IID_IPropertyBag, reinterpret_cast void** ( pPropBag)); if (SUCCEEDED(hr)) { VARIANT varName; VariantInit( varName); hr = pPropBag- Read(L"FriendlyName", varName, 0); if (SUCCEEDED(hr)) { size_t len = wcslen(varName.bstrVal) + 1; PWSTR pName = new WCHAR [len]; StringCchCopyW(pName, len, varName.bstrVal); CW2AEX buf(varName.bstrVal); pCtrl- SetItemData(pCtrl- AddString(buf), (DWORD)pName); } VariantClear( varName); // contained within a loop, decrement the reference count SAFE_RELEASE(pPropBag); } SAFE_RELEASE(pMoniker); } } } } else { hr = E_POINTER; } return hr; } //----------------------------------------------------------------------------- // PopulateVideoControl // Fill video format combo box with supported video formats using the IAMStreamConfig // interface. HRESULT CDecklinkCaptureDlg PopulateVideoControl() { HRESULT hr = S_OK; if (m_pVideoCapture) { // free mediatypes attached to format controls int count = m_videoFormatCtrl.GetCount(); if (count) { for (int item=0; item count; ++item) { DeleteMediaType((AM_MEDIA_TYPE*)m_videoFormatCtrl.GetItemData(item)); } m_videoFormatCtrl.ResetContent(); } // locate the video capture pin and QI for stream control CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pVideoCapture, MEDIATYPE_Video, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // loop through all the capabilities (video formats) and populate the control int count, size; hr = pISC- GetNumberOfCapabilities( count, size); if (SUCCEEDED(hr)) { if (sizeof(VIDEO_STREAM_CONFIG_CAPS) == size) { AM_MEDIA_TYPE* pmt = NULL; VIDEO_STREAM_CONFIG_CAPS vscc; VIDEOINFOHEADER* pvih = NULL; for (int index=0; index count; ++index) { hr = pISC- GetStreamCaps(index, pmt, reinterpret_cast BYTE* ( vscc)); if (SUCCEEDED(hr)) { char buffer[128]; WORD PixelFormat; float FrameRate; ZeroMemory(buffer, sizeof(buffer)); pvih = (VIDEOINFOHEADER*)pmt- pbFormat; char* pPixelFormatLUT[] = {"4 2 2", "4 4 4"}; if (pvih- bmiHeader.biBitCount == 16) PixelFormat = 8; else if (pvih- bmiHeader.biBitCount == 20) PixelFormat = 10; else PixelFormat = pvih- bmiHeader.biBitCount; // provide a useful description of the formats if (486 == pvih- bmiHeader.biHeight) { if (417083 == pvih- AvgTimePerFrame) { StringCbPrintfA(buffer, sizeof(buffer), "NTSC %d-bit %s (3 2 pulldown removal)", PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { StringCbPrintfA(buffer, sizeof(buffer), "NTSC %d-bit %s", PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } } else if (576 == pvih- bmiHeader.biHeight) { StringCbPrintfA(buffer, sizeof(buffer), "PAL %d-bit %s", PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { char* pFrameRateFormat[] = {"%.2f", "%.0f"}; FrameRate = (float)(long)UNITS / pvih- AvgTimePerFrame; if ((720 == pvih- bmiHeader.biHeight) (59.94 FrameRate)) { if ((FrameRate - (int)FrameRate) 0.01) { StringCbPrintfA(buffer, sizeof(buffer), "HD720 %.2fp %d-bit %s (Overcranked 60p)", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { StringCbPrintfA(buffer, sizeof(buffer), "HD720 %.0fp %d-bit %s (Overcranked 60p)", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } } else if ((720 == pvih- bmiHeader.biHeight) (59.94 = FrameRate)) { if ((FrameRate - (int)FrameRate) 0.01) { StringCbPrintfA(buffer, sizeof(buffer), "HD720 %.2fp %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { StringCbPrintfA(buffer, sizeof(buffer), "HD720 %.0fp %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } } else if ((1080 == pvih- bmiHeader.biHeight) (50.00 = FrameRate)) { if ((FrameRate - (int)FrameRate) 0.01) { StringCbPrintfA(buffer, sizeof(buffer), "HD1080 %.2fi %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { StringCbPrintfA(buffer, sizeof(buffer), "HD1080 %.0fi %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } } else { if ((FrameRate - (int)FrameRate) 0.01) { StringCbPrintfA(buffer, sizeof(buffer), "HD1080 %.2fPsF %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { StringCbPrintfA(buffer, sizeof(buffer), "HD1080 %.0fPsF %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } } } // add the item description to combo box int n = m_videoFormatCtrl.AddString(buffer); // store media type pointer in item s data section m_videoFormatCtrl.SetItemData(n, (DWORD_PTR)pmt); // set default format if ((pvih- AvgTimePerFrame == m_vihDefault.AvgTimePerFrame) (pvih- bmiHeader.biWidth == m_vihDefault.bmiHeader.biWidth) (pvih- bmiHeader.biHeight == m_vihDefault.bmiHeader.biHeight) (pvih- bmiHeader.biBitCount == m_vihDefault.bmiHeader.biBitCount)) { m_videoFormatCtrl.SetCurSel(n); pISC- SetFormat(pmt); } } } } else { m_videoFormatCtrl.AddString("ERROR Unable to retrieve video formats"); } } } } else { hr = E_POINTER; } return hr; } //----------------------------------------------------------------------------- // PopulateAudioControl // Fill audio format combo box with supported audio formats using the IAMStreamConfig // interface. HRESULT CDecklinkCaptureDlg PopulateAudioControl() { HRESULT hr = S_OK; if (m_pAudioCapture) { // free mediatypes attached to format controls int count = m_audioFormatCtrl.GetCount(); if (count) { for (int item=0; item count; ++item) { DeleteMediaType((AM_MEDIA_TYPE*)m_audioFormatCtrl.GetItemData(item)); } m_audioFormatCtrl.ResetContent(); } // locate the audio capture pin and QI for stream control CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pAudioCapture, MEDIATYPE_Audio, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // loop through all the capabilities (audio formats) and populate the control int count, size; hr = pISC- GetNumberOfCapabilities( count, size); if (SUCCEEDED(hr)) { if (sizeof(AUDIO_STREAM_CONFIG_CAPS) == size) { AM_MEDIA_TYPE* pmt = NULL; AUDIO_STREAM_CONFIG_CAPS ascc; WAVEFORMATEX* pwfex = NULL; for (int index=0; index count; ++index) { hr = pISC- GetStreamCaps(index, pmt, reinterpret_cast BYTE* ( ascc)); if (SUCCEEDED(hr)) { char buffer[32]; ZeroMemory(buffer, sizeof(buffer)); pwfex = (WAVEFORMATEX*)pmt- pbFormat; // provide a useful description of the formats if (1 == pwfex- nChannels) { StringCbPrintfA(buffer, sizeof(buffer), "%d channel, %2.1fkHz, %d-bit", (int)pwfex- nChannels, (float)pwfex- nSamplesPerSec / 1000, (int)pwfex- wBitsPerSample); } else { StringCbPrintfA(buffer, sizeof(buffer), "%d channels, %2.1fkHz, %d-bit", (int)pwfex- nChannels, (float)pwfex- nSamplesPerSec / 1000, (int)pwfex- wBitsPerSample); } // add the item description to combo box int n = m_audioFormatCtrl.AddString(buffer); // store media type pointer in item s data section m_audioFormatCtrl.SetItemData(n, (DWORD_PTR)pmt); // set default format if ((pwfex- wFormatTag == m_wfexDefault.wFormatTag) (pwfex- nChannels == m_wfexDefault.nChannels) (pwfex- nSamplesPerSec == m_wfexDefault.nSamplesPerSec) (pwfex- nAvgBytesPerSec == m_wfexDefault.nAvgBytesPerSec)) { m_audioFormatCtrl.SetCurSel(n); pISC- SetFormat(pmt); } } } } else { m_audioFormatCtrl.AddString("ERROR Unable to retrieve audio formats"); } } } } else { hr = E_POINTER; } return hr; } //----------------------------------------------------------------------------- // PopulateCompressionControl // Fill compression control with a selection of video compressors, locate the // encoders and add them to the combo box if they exist. HRESULT CDecklinkCaptureDlg PopulateCompressionControl() { int n = m_compressionCtrl.AddString("Uncompressed"); m_compressionCtrl.SetItemData(n, (DWORD_PTR)ENC_NONE); // search for the DV encoder, MPEG encoder and WM encoder IBaseFilter* pFilter = NULL; HRESULT hr = CoCreateInstance(CLSID_DVVideoEnc, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast void** ( pFilter)); if (SUCCEEDED(hr)) { n = m_compressionCtrl.SetCurSel(m_compressionCtrl.AddString("DV Video Encoder")); m_compressionCtrl.SetItemData(n, (DWORD_PTR)ENC_DV); SAFE_RELEASE(pFilter); } hr = CoCreateInstance(CLSID_WMAsfWriter, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast void** ( pFilter)); if (SUCCEEDED(hr)) { n = m_compressionCtrl.SetCurSel(m_compressionCtrl.AddString("Windows Media Encoder")); m_compressionCtrl.SetItemData(n, (DWORD_PTR)ENC_WM); SAFE_RELEASE(pFilter); } m_compressionCtrl.SetCurSel(m_compressor); return S_OK; } //----------------------------------------------------------------------------- // OnCbnSelchangeComboVideodevice // Rebuild graph with selected capture device void CDecklinkCaptureDlg OnCbnSelchangeComboVideodevice() { SAFE_RELEASE(m_pVideoCapture);// release our outstanding reference // remove intermediate filters, since the device selection has changed the capture device will also be removed HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { // rebuild graph with new capture device selection PWSTR pName = (PWSTR)m_videoDeviceCtrl.GetItemData(m_videoDeviceCtrl.GetCurSel()); if (pName) { hr = CDSUtils AddFilter2(m_pGraph, CLSID_VideoInputDeviceCategory, pName, m_pVideoCapture); if (SUCCEEDED(hr)) { // as the device has changed get the current operating format so that the control // and display this as the current selection CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pVideoCapture, MEDIATYPE_Video, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // get the current format of the device to set the current selection of the control AM_MEDIA_TYPE* pamt = NULL; hr = pISC- GetFormat( pamt); if (SUCCEEDED(hr)) { if (pamt- pbFormat) { m_vihDefault = *(VIDEOINFOHEADER*)pamt- pbFormat; } DeleteMediaType(pamt); } } hr = PopulateVideoControl();// repopulate the control with formats from the new device if (SUCCEEDED(hr)) { hr = CreatePreviewGraph();// rebuild the graph with the new device } } } else { hr = E_POINTER; } } } //----------------------------------------------------------------------------- // OnCbnSelchangeComboAudiodevice // Rebuild graph with selected capture device void CDecklinkCaptureDlg OnCbnSelchangeComboAudiodevice() { SAFE_RELEASE(m_pAudioCapture);// release our outstanding reference // remove intermediate filters, since the device selection has changed the capture device will also be removed HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { PWSTR pName = (PWSTR)m_audioDeviceCtrl.GetItemData(m_audioDeviceCtrl.GetCurSel()); if (pName) { hr = CDSUtils AddFilter2(m_pGraph, CLSID_AudioInputDeviceCategory, pName, m_pAudioCapture); if (SUCCEEDED(hr)) { // as the device has changed get the current operating format so that the control // and display this as the current selection CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pAudioCapture, MEDIATYPE_Audio, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // get the current format of the device to set the current selection of the control AM_MEDIA_TYPE* pamt = NULL; hr = pISC- GetFormat( pamt); if (SUCCEEDED(hr)) { if (pamt- pbFormat) { m_wfexDefault = *(WAVEFORMATEX*)pamt- pbFormat; } DeleteMediaType(pamt); } } hr = PopulateAudioControl();// repopulate the control with formats from the new device if (SUCCEEDED(hr)) { hr = CreatePreviewGraph();// rebuild the graph with the new device } } } else { hr = E_POINTER; } } } //----------------------------------------------------------------------------- // OnCbnSelchangeComboVideoformats // Rebuild preview graph if format selection changed void CDecklinkCaptureDlg OnCbnSelchangeComboVideoformats() { HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { // locate the video capture pin and QI for stream control CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pVideoCapture, MEDIATYPE_Video, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // set the new media format AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)m_videoFormatCtrl.GetItemData(m_videoFormatCtrl.GetCurSel()); m_vihDefault = *(VIDEOINFOHEADER*)pmt- pbFormat; ASSERT(sizeof(VIDEOINFOHEADER) = pmt- cbFormat); hr = pISC- SetFormat(pmt); if (SUCCEEDED(hr)) { // save the new format EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("VideoFormat", reinterpret_cast const BYTE* ( m_vihDefault), sizeof(m_vihDefault))); // update compression control, we don t have an HD compression filter so disable compression for HD formats if (576 m_vihDefault.bmiHeader.biHeight) { m_compressor = 0; m_compressionCtrl.SetCurSel(m_compressor); // save the new state EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("VideoCompressor", reinterpret_cast const BYTE* ( m_compressor), sizeof(m_compressor))); m_bEnableCompressionCtrl = FALSE; } else { m_bEnableCompressionCtrl = TRUE; } EnableControls(); // rebuild the graph hr = CreatePreviewGraph(); } } } } //----------------------------------------------------------------------------- // OnCbnSelchangeComboAudioformats // Rebuild preview graph if format selection changed void CDecklinkCaptureDlg OnCbnSelchangeComboAudioformats() { HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { // locate the audio capture pin and QI for stream control CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pAudioCapture, MEDIATYPE_Audio, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // set the new media format AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)m_audioFormatCtrl.GetItemData(m_audioFormatCtrl.GetCurSel()); m_wfexDefault = *(WAVEFORMATEX*)pmt- pbFormat; ASSERT(sizeof(WAVEFORMATEX) == pmt- cbFormat); hr = pISC- SetFormat(pmt); if (SUCCEEDED(hr)) { // save the new format EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("AudioFormat", reinterpret_cast const BYTE* ( m_wfexDefault), sizeof(m_wfexDefault))); // rebuild the graph hr = CreatePreviewGraph(); } } } } //----------------------------------------------------------------------------- // OnCbnSelchangeComboCompression // Rebuild preview graph if compression selection changed void CDecklinkCaptureDlg OnCbnSelchangeComboCompression() { HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { // save the new state m_compressor = m_compressionCtrl.GetCurSel(); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("VideoCompressor", reinterpret_cast const BYTE* ( m_compressor), sizeof(m_compressor))); // rebuild the graph hr = CreatePreviewGraph(); } } //----------------------------------------------------------------------------- // OnBnClickedCheckAudiomute // Rebuild the capture graph to reflect the new audio setting void CDecklinkCaptureDlg OnBnClickedCheckAudiomute() { CButton* pCheck = (CButton*)GetDlgItem(IDC_CHECK_AUDIOMUTE); if (pCheck) { m_bAudioMute = pCheck- GetState() 0x0003; HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { // save the new state EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("AudioMute", reinterpret_cast const BYTE* ( m_bAudioMute), sizeof(m_bAudioMute))); // rebuild the graph which reflects the new audio setting hr = CreatePreviewGraph(); } } } //----------------------------------------------------------------------------- // OnBnClickedButtonBrowse // Create a file open dialog to browse for a file location void CDecklinkCaptureDlg OnBnClickedButtonBrowse() { char BASED_CODE szFilters[] = "Windows Media Files|*.avi;*.asf;*.wmv|All Files (*.*)|*.*||"; char* pExt[] = {"*.avi", "*.avi", "*.asf;*.wmv"}; CFileDialog FileDlg(TRUE, "Windows Media Files", pExt[m_compressor], 0, szFilters, this); if (FileDlg.DoModal() == IDOK) { m_captureFile = FileDlg.GetPathName(); m_captureFileCtrl.SetWindowText(m_captureFile); } } //----------------------------------------------------------------------------- // OnBnClickedButtonCapture // Create a capture graph a start capture void CDecklinkCaptureDlg OnBnClickedButtonCapture() { HRESULT hr = CreateCaptureGraph(); if (SUCCEEDED(hr)) { if (m_pControl) { hr = m_pControl- Run(); if (SUCCEEDED(hr)) { DisableControls(); } } } } //----------------------------------------------------------------------------- // OnBnClickedButtonStop // Stop capture and revert to preview void CDecklinkCaptureDlg OnBnClickedButtonStop() { HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { hr = CreatePreviewGraph(); if (SUCCEEDED(hr)) { EnableControls(); } } } //----------------------------------------------------------------------------- // EnableControls // void CDecklinkCaptureDlg EnableControls(void) { CWnd* pWnd = GetDlgItem(IDC_COMBO_VIDEOFORMATS); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_COMBO_AUDIOFORMATS); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_CHECK_AUDIOMUTE); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_COMBO_COMPRESSION); m_bEnableCompressionCtrl = (576 m_vihDefault.bmiHeader.biHeight) ? FALSE TRUE;// don t have an HDV codec do disable compression control for HD formats pWnd- EnableWindow(m_bEnableCompressionCtrl); pWnd = GetDlgItem(IDC_EDIT_CAPTUREFILE); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_BUTTON_BROWSE); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_BUTTON_CAPTURE); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_BUTTON_STOP); pWnd- EnableWindow(FALSE); } //----------------------------------------------------------------------------- // DisableControls // void CDecklinkCaptureDlg DisableControls(void) { CWnd* pWnd = GetDlgItem(IDC_COMBO_VIDEOFORMATS); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_COMBO_AUDIOFORMATS); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_CHECK_AUDIOMUTE); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_COMBO_COMPRESSION); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_EDIT_CAPTUREFILE); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_BUTTON_BROWSE); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_BUTTON_CAPTURE); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_BUTTON_STOP); pWnd- EnableWindow(TRUE); } //----------------------------------------------------------------------------- // QueryRegistry // retrieve previous media formats from registry void CDecklinkCaptureDlg QueryRegistry(void) { if (ERROR_SUCCESS == m_regUtils.Open("DecklinkCaptureSample")) { EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.GetBinary("VideoFormat", reinterpret_cast LPBYTE ( m_vihDefault), sizeof(m_vihDefault))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.GetBinary("AudioFormat", reinterpret_cast LPBYTE ( m_wfexDefault), sizeof(m_wfexDefault))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.GetBinary("AudioMute", reinterpret_cast LPBYTE ( m_bAudioMute), sizeof(m_bAudioMute))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.GetBinary("VideoCompressor", reinterpret_cast LPBYTE ( m_compressor), sizeof(m_compressor))); WCHAR captureFile[MAX_PATH]; ZeroMemory(captureFile, sizeof(captureFile)); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.GetString("CaptureFile", reinterpret_cast LPBYTE (captureFile), sizeof(captureFile))); m_captureFile = captureFile; } else { // create the key and registry values if (ERROR_SUCCESS == m_regUtils.Create("DecklinkCaptureSample")) { EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("VideoFormat", reinterpret_cast const BYTE* ( m_vihDefault), sizeof(m_vihDefault))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("AudioFormat", reinterpret_cast const BYTE* ( m_wfexDefault), sizeof(m_wfexDefault))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("AudioMute", reinterpret_cast const BYTE* ( m_bAudioMute), sizeof(m_bAudioMute))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("VideoCompressor", reinterpret_cast const BYTE* ( m_compressor), sizeof(m_compressor))); } } // update mute audio check box control CButton* pButton = (CButton*)GetDlgItem(IDC_CHECK_AUDIOMUTE); pButton- SetCheck(m_bAudioMute); }
https://w.atwiki.jp/ppnlab/pages/25.html
ds
https://w.atwiki.jp/bmd_intensity/pages/26.html
//----------------------------------------------------------------------------- // $Id DecklinkCaptureDlg.cpp,v 1.9 2006/04/11 01 11 07 ivanr Exp $ // // Desc DirectShow capture sample // // Copyright (c) Blackmagic Design 2005. All rights reserved. //----------------------------------------------------------------------------- #include "stdafx.h" #include "DecklinkCapture.h" #include "DecklinkCaptureDlg.h" #include initguid.h // TODO move this to a lib #include "DecklinkSample_uuids.h" #undef lstrlenW #ifdef _DEBUG #define new DEBUG_NEW #endif #define WM_GRAPHNOTIFYWM_APP+1// for Filter Graph event notification //----------------------------------------------------------------------------- // CAboutDlg //----------------------------------------------------------------------------- // CAboutDlg dialog used for App About class CAboutDlg public CDialog { public CAboutDlg(); // Dialog Data enum { IDD = IDD_ABOUTBOX }; protected virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support // Implementation protected DECLARE_MESSAGE_MAP() }; CAboutDlg CAboutDlg() CDialog(CAboutDlg IDD) { } void CAboutDlg DoDataExchange(CDataExchange* pDX) { CDialog DoDataExchange(pDX); } BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) END_MESSAGE_MAP() //----------------------------------------------------------------------------- // CDecklinkCaptureDlg dialog //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Constructor // CDecklinkCaptureDlg CDecklinkCaptureDlg(CWnd* pParent /*=NULL*/) CDialog(CDecklinkCaptureDlg IDD, pParent) , m_pIVW(NULL) { m_hIcon = AfxGetApp()- LoadIcon(IDR_MAINFRAME); } //----------------------------------------------------------------------------- // DoDataExchange // void CDecklinkCaptureDlg DoDataExchange(CDataExchange* pDX) { CDialog DoDataExchange(pDX); DDX_Control(pDX, IDC_COMBO_VIDEOFORMATS, m_videoFormatCtrl); DDX_Control(pDX, IDC_COMBO_AUDIOFORMATS, m_audioFormatCtrl); DDX_Control(pDX, IDC_STATIC_PREVIEW, m_preview); DDX_Control(pDX, IDC_EDIT_CAPTUREFILE, m_captureFileCtrl); DDX_Control(pDX, IDC_COMBO_COMPRESSION, m_compressionCtrl); DDX_Control(pDX, IDC_COMBO_VIDEODEVICE, m_videoDeviceCtrl); DDX_Control(pDX, IDC_COMBO_AUDIODEVICE, m_audioDeviceCtrl); } BEGIN_MESSAGE_MAP(CDecklinkCaptureDlg, CDialog) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() //}}AFX_MSG_MAP ON_CBN_SELCHANGE(IDC_COMBO_VIDEOFORMATS, OnCbnSelchangeComboVideoformats) ON_CBN_SELCHANGE(IDC_COMBO_AUDIOFORMATS, OnCbnSelchangeComboAudioformats) ON_BN_CLICKED(IDC_CHECK_AUDIOMUTE, OnBnClickedCheckAudiomute) ON_BN_CLICKED(IDC_BUTTON_BROWSE, OnBnClickedButtonBrowse) ON_BN_CLICKED(IDC_BUTTON_CAPTURE, OnBnClickedButtonCapture) ON_BN_CLICKED(IDC_BUTTON_STOP, OnBnClickedButtonStop) ON_CBN_SELCHANGE(IDC_COMBO_COMPRESSION, OnCbnSelchangeComboCompression) ON_CBN_SELCHANGE(IDC_COMBO_VIDEODEVICE, OnCbnSelchangeComboVideodevice) ON_CBN_SELCHANGE(IDC_COMBO_AUDIODEVICE, OnCbnSelchangeComboAudiodevice) END_MESSAGE_MAP() //----------------------------------------------------------------------------- // CDecklinkCaptureDlg message handlers //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // OnInitDialog // Called before the dialog is displayed, use this message handler to initialise // our app BOOL CDecklinkCaptureDlg OnInitDialog() { CDialog OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu- AppendMenu(MF_SEPARATOR); pSysMenu- AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application s main window is not a dialog SetIcon(m_hIcon, TRUE);// Set big icon SetIcon(m_hIcon, FALSE);// Set small icon // create a basic capture graph and preview the incoming video m_pGraph = NULL; m_pVideoCapture = NULL; m_pAudioCapture = NULL; m_pVideoRenderer = NULL; m_pSmartT = NULL; m_pControl = NULL; m_pIVW = NULL; m_pMediaEvent = NULL; m_ROTRegister = 0; m_bAudioMute = FALSE; m_compressor = 0; m_bEnableCompressionCtrl = TRUE; m_captureFile = " Select File "; // initialise default video media type ZeroMemory( m_vihDefault, sizeof(m_vihDefault)); m_vihDefault.AvgTimePerFrame = 333667; m_vihDefault.bmiHeader.biWidth = 720; m_vihDefault.bmiHeader.biHeight = 486; m_vihDefault.bmiHeader.biBitCount = 16; m_vihDefault.bmiHeader.biCompression = YVYU ; // initialise default audio media type ZeroMemory( m_wfexDefault, sizeof(m_wfexDefault)); m_wfexDefault.nChannels = 2;// the only field of interest // retrieve last state QueryRegistry(); m_captureFileCtrl.SetWindowText(m_captureFile); EnableControls(); // create a preview graph // add the filters that will be used by all the graphs; preview, uncompressed capture, dv capture, // mpeg capture and windows media capture HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, reinterpret_cast void** ( m_pGraph)); if (SUCCEEDED(hr)) { #ifdef _DEBUG hr = CDSUtils AddGraphToRot(m_pGraph, m_ROTRegister); #endif hr = m_pGraph- QueryInterface(IID_IMediaControl, reinterpret_cast void** ( m_pControl)); if (SUCCEEDED(hr)) { // locate the video capture devices hr = PopulateDeviceControl( CLSID_VideoInputDeviceCategory, m_videoDeviceCtrl); if (SUCCEEDED(hr)) { hr = PopulateDeviceControl( CLSID_AudioInputDeviceCategory, m_audioDeviceCtrl); if (SUCCEEDED(hr)) { PWSTR pVideoName = (PWSTR)m_videoDeviceCtrl.GetItemData(m_videoDeviceCtrl.SetCurSel(0)); PWSTR pAudioName = (PWSTR)m_audioDeviceCtrl.GetItemData(m_audioDeviceCtrl.SetCurSel(0)); if (pVideoName pAudioName) { hr = CDSUtils AddFilter2(m_pGraph, CLSID_VideoInputDeviceCategory, pVideoName, m_pVideoCapture); if (SUCCEEDED(hr)) { hr = CDSUtils AddFilter2(m_pGraph, CLSID_AudioInputDeviceCategory, pAudioName, m_pAudioCapture); if (SUCCEEDED(hr)) { PopulateVideoControl();// populate the video format control with the video formats of the currently selected device PopulateAudioControl();// populate the audio format control with the audio formats of the currently selected device PopulateCompressionControl(); // locate video screen renderer for the preview window hr = CDSUtils AddFilter(m_pGraph, CLSID_VideoRendererDefault, L"Video Renderer", m_pVideoRenderer); if (SUCCEEDED(hr)) { hr = CreatePreviewGraph(); } } } } } } } } return TRUE; // return TRUE unless you set the focus to a control } //----------------------------------------------------------------------------- // DestroyWindow // Called when the window is being destroyed, clean up and free all resources. BOOL CDecklinkCaptureDlg DestroyWindow() { m_regUtils.Close(); #ifdef _DEBUG CDSUtils RemoveGraphFromRot(m_ROTRegister); #endif DestroyGraph(); SAFE_RELEASE(m_pControl); // Hide Video Window and remove owner. This has to be done prior to // destroying any window that displays video/still. if (m_pIVW) { m_pIVW- put_Visible(OAFALSE); m_pIVW- put_Owner(NULL); } SAFE_RELEASE(m_pIVW); SAFE_RELEASE(m_pMediaEvent); SAFE_RELEASE(m_pVideoRenderer); SAFE_RELEASE(m_pAudioCapture); SAFE_RELEASE(m_pVideoCapture); SAFE_RELEASE(m_pGraph); // free mediatypes attached to format controls int count = m_videoFormatCtrl.GetCount(); for (int item=0; item count; ++item) { DeleteMediaType((AM_MEDIA_TYPE*)m_videoFormatCtrl.GetItemData(item)); } count = m_audioFormatCtrl.GetCount(); for (int item=0; item count; ++item) { DeleteMediaType((AM_MEDIA_TYPE*)m_audioFormatCtrl.GetItemData(item)); } // release the device names attached to the item s data count = m_videoDeviceCtrl.GetCount(); for (item=0; item count; ++item) { PWSTR pName = (PWSTR)m_videoDeviceCtrl.GetItemData(item); delete [] pName; } count = m_audioDeviceCtrl.GetCount(); for (item=0; item count; ++item) { PWSTR pName = (PWSTR)m_audioDeviceCtrl.GetItemData(item); delete [] pName; } return CDialog DestroyWindow(); } //----------------------------------------------------------------------------- // OnSysCommand // void CDecklinkCaptureDlg OnSysCommand(UINT nID, LPARAM lParam) { if ((nID 0xFFF0) == IDM_ABOUTBOX) { CAboutDlg dlgAbout; dlgAbout.DoModal(); } else { CDialog OnSysCommand(nID, lParam); } } //----------------------------------------------------------------------------- // OnPaint // If you add a minimize button to your dialog, you will need the code below // to draw the icon. For MFC applications using the document/view model, // this is automatically done for you by the framework. void CDecklinkCaptureDlg OnPaint() { if (IsIconic()) { CPaintDC dc(this); // device context for painting SendMessage(WM_ICONERASEBKGND, reinterpret_cast WPARAM (dc.GetSafeHdc()), 0); // Center icon in client rectangle int cxIcon = GetSystemMetrics(SM_CXICON); int cyIcon = GetSystemMetrics(SM_CYICON); CRect rect; GetClientRect( rect); int x = (rect.Width() - cxIcon + 1) / 2; int y = (rect.Height() - cyIcon + 1) / 2; // Draw the icon dc.DrawIcon(x, y, m_hIcon); } else { CDialog OnPaint(); } } //----------------------------------------------------------------------------- // HandleGraphEvent // At the moment we just read the event, discard it and release memory used to store it. void CDecklinkCaptureDlg HandleGraphEvent(void) { LONG lEventCode, lEventParam1, lEventParam2; if (!m_pMediaEvent) { return; } while (SUCCEEDED(m_pMediaEvent- GetEvent( lEventCode, reinterpret_cast LONG_PTR * ( lEventParam1), reinterpret_cast LONG_PTR * ( lEventParam2), 0))) { // just free memory associated with event m_pMediaEvent- FreeEventParams(lEventCode, lEventParam1, lEventParam2); } } //----------------------------------------------------------------------------- // WindowProc // Have to add our own message handling loop to handle events from the preview video // window and to pass Window events onto it - this is so it redraws itself correctly etc. LRESULT CDecklinkCaptureDlg WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_GRAPHNOTIFY HandleGraphEvent(); break; } // Pass all msgs to video window. vid window exists as child of static // picture frame. This ensures video window redraws itself etc. if (m_pIVW) { m_pIVW- NotifyOwnerMessage(reinterpret_cast LONG_PTR (m_hWnd) /* from me */, message, wParam, lParam); } return CDialog WindowProc(message, wParam, lParam); } //----------------------------------------------------------------------------- // OnQueryDragIcon // The system calls this function to obtain the cursor to display while the user drags // the minimized window. HCURSOR CDecklinkCaptureDlg OnQueryDragIcon() { return static_cast HCURSOR (m_hIcon); } //----------------------------------------------------------------------------- // CreatePreviewGraph // Create a graph to preview the input // NOTE There are many ways of building graphs, you could opt for the ICaptureGraphBuilder interface which would // make things are lot simpler, however it doesn t always build the most efficient graphs. HRESULT CDecklinkCaptureDlg CreatePreviewGraph() { HRESULT hr = S_OK; if (m_pGraph) { // locate smart-T // NOTE The smart-T appears to hold references to its upstream connections even when its input pin // is diconnected. The smart-T has to be removed from the graph in order to clear these references which // is why the filter is enumerated and added every time the preview graph is built and removed whenever // it is destroyed. ASSERT(NULL == m_pSmartT); hr = CDSUtils AddFilter(m_pGraph, CLSID_SmartTee, L"Smart Tee", m_pSmartT); if (SUCCEEDED(hr)) { // DV preview is slightly different to all other previews if (ENC_DV != m_compressionCtrl.GetItemData(m_compressionCtrl.GetCurSel())) { // uncompressed, mpeg and wm preview // create the following // // Decklink Video Capture - Smart-T - AVI Decompressor - Video Renderer // Decklink Audio Capture - Default Audio Renderer // // render the preview pin on the smart-T filter // first connect the Decklink video capture pin to the smart-T hr = CDSUtils ConnectFilters(m_pGraph, m_pVideoCapture, NULL, m_pSmartT, NULL); if (SUCCEEDED(hr)) { // now connect the preview pin of the smart-T to the video renderer hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, L"Preview", m_pVideoRenderer, NULL); } } else { // DV Preview // create the following // // Decklink Video Capture - AVI Decompressor - Smart-T - Colour Space Converter - Video Renderer // Decklink Audio Capture - Default Audio Renderer // // this is a more efficient graph than created by the ICaptureGraphBuilder2 interface // add the AVI decompressor and colour space converter filters CComPtr IBaseFilter pAVIDecompressor = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_AVIDec, L"AVI Decompressor", pAVIDecompressor); if (SUCCEEDED(hr)) { CComPtr IBaseFilter pColourSpaceConverter = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_Colour, L"Color Space Converter", pColourSpaceConverter); if (SUCCEEDED(hr)) { // conect the Decklink video capture pin to the AVI decompressor hr = CDSUtils ConnectFilters(m_pGraph, m_pVideoCapture, NULL, pAVIDecompressor, NULL); if (SUCCEEDED(hr)) { // connect AVI decompressor to the smart-T hr = CDSUtils ConnectFilters(m_pGraph, pAVIDecompressor, NULL, m_pSmartT, NULL); if (SUCCEEDED(hr)) { // connect the preview pin of the smart-T to the colour space converter hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, L"Preview", pColourSpaceConverter, NULL); if (SUCCEEDED(hr)) { // connect the colour space converter to the video renderer hr = CDSUtils ConnectFilters(m_pGraph, pColourSpaceConverter, NULL, m_pVideoRenderer, NULL); } } } } } } } } else { hr = E_POINTER; } if (SUCCEEDED(hr)) { // the video path has been connected, initialise the preview window InitialiseVideoPreview(); // optionally connect the audio path if (FALSE == m_bAudioMute) { // connect the Decklink audio capture pin to the mux hr = CDSUtils RenderFilter(m_pGraph, m_pAudioCapture, L"Capture"); } // run the graph so that we can preview the input video if (m_pControl) { hr = m_pControl- Run(); } else { hr = E_POINTER; } } return hr; } //----------------------------------------------------------------------------- // CreateCaptureGraph // Create a graph to capture the input HRESULT CDecklinkCaptureDlg CreateCaptureGraph() { HRESULT hr = S_OK; // tack the file writer onto the preview graph if (m_pGraph m_pControl) { // stop the graph as we are about to modify it m_pControl- Stop(); // remove the default audio renderer so the Decklink audio capture filter // can be connected to the AVI mux, we will not preview audio whilst capturing CComPtr IPin pIPinOutput = NULL; hr = CDSUtils GetPin(m_pAudioCapture, L"Capture", pIPinOutput); if (SUCCEEDED(hr)) { // to disconnect both pins must be disconnected // find the pin connected to the Decklink audio capture pin CComPtr IPin pIPinConnection = NULL; hr = pIPinOutput- ConnectedTo( pIPinConnection); if (SUCCEEDED(hr)) { // disconnect the pins hr = m_pGraph- Disconnect(pIPinOutput); hr = m_pGraph- Disconnect(pIPinConnection); // get the owning filter of the downstream pin and remove it from the graph PIN_INFO pinInfo = {0}; hr = pIPinConnection- QueryPinInfo( pinInfo); if (SUCCEEDED(hr)) { if (pinInfo.pFilter) { hr = m_pGraph- RemoveFilter(pinInfo.pFilter); pinInfo.pFilter- Release(); } } } } // retrieve the capture filename m_captureFileCtrl.GetWindowText(m_captureFile); // store filename USES_CONVERSION; WCHAR captureFile[MAX_PATH]; wcsncpy(captureFile, A2W(m_captureFile), MAX_PATH); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetString("CaptureFile", reinterpret_cast const BYTE* (captureFile), sizeof(captureFile))); // decide the type of capture graph to build switch (m_compressionCtrl.GetItemData(m_compressionCtrl.GetCurSel())) { default case ENC_NONE hr = CreateUncompressedCaptureGraph(); break; case ENC_DV hr = CreateDVCaptureGraph(); break; case ENC_WM hr = CreateWMCaptureGraph(); break; } if (FAILED(hr)) { // there was a problem building the capture graph, issue a message // and rebuild preview graph char buffer[128]; StringCbPrintfA(buffer, sizeof(buffer), "The error 0x%08lx was detected when creating the capture graph with the following file name \r\n\r\n %s ", hr, m_captureFile); MessageBox(buffer, _T("Error"), MB_ICONERROR); OnBnClickedButtonStop();// destroy broken capture graph, build preview graph and enable controls } } else { hr = E_POINTER; } return hr; } //----------------------------------------------------------------------------- // CreateUncompressedCaptureGraph // Create an optimum uncompressed capture graph HRESULT CDecklinkCaptureDlg CreateUncompressedCaptureGraph() { HRESULT hr = S_OK; // uncompressed capture // locate the AVI mux and file writer filters and add them to the graph CComPtr IBaseFilter pAVIMux = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_AviDest , L"AVI Mux", pAVIMux); if (SUCCEEDED(hr)) { CComPtr IBaseFilter pFileWriter = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_FileWriter, L"File writer", pFileWriter); if (SUCCEEDED(hr)) { // set the output filename CComQIPtr IFileSinkFilter, IID_IFileSinkFilter pIFS = pFileWriter; if (pIFS) { USES_CONVERSION;// for T2W macro hr = pIFS- SetFileName(T2W(m_captureFile), NULL); if (SUCCEEDED(hr)) { // connect the smart-T capture pin to the mux hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, L"Capture", pAVIMux, NULL); if (SUCCEEDED(hr)) { // connect the mux to the file writer hr = CDSUtils ConnectFilters(m_pGraph, pAVIMux, NULL, pFileWriter, NULL); if (SUCCEEDED(hr)) { // video path connected now optionally connect the audio path if (FALSE == m_bAudioMute) { // connect the Decklink audio capture pin to the mux hr = CDSUtils ConnectFilters(m_pGraph, m_pAudioCapture, L"Capture", pAVIMux, NULL); } if (SUCCEEDED(hr)) { m_pControl- Run(); } } } } } } } return hr; } //----------------------------------------------------------------------------- // CreateDVCaptureGraph // Create an optimum DV capture graph // NOTE that this will only work for SD HRESULT CDecklinkCaptureDlg CreateDVCaptureGraph() { HRESULT hr = S_OK; // locate the DV encoder, AVI mux and file writer filters and add them to the graph CComPtr IBaseFilter pDVEncoder = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_DVVideoEnc, L"DV Video Encoder", pDVEncoder); if (SUCCEEDED(hr)) { CComPtr IBaseFilter pAVIMux = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_AviDest , L"AVI Mux", pAVIMux); if (SUCCEEDED(hr)) { CComPtr IBaseFilter pFileWriter = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_FileWriter, L"File writer", pFileWriter); if (SUCCEEDED(hr)) { // set the output filename CComQIPtr IFileSinkFilter, IID_IFileSinkFilter pIFS = pFileWriter; if (pIFS) { USES_CONVERSION;// for T2W macro hr = pIFS- SetFileName(T2W(m_captureFile), NULL); if (SUCCEEDED(hr)) { // configure the DV encoder CComQIPtr IDVEnc, IID_IDVEnc pIDV = pDVEncoder; if (pIDV) { // located a DV compression filter, set the format int videoFormat, dvFormat, resolution; hr = pIDV- get_IFormatResolution( videoFormat, dvFormat, resolution, FALSE, NULL); if (SUCCEEDED(hr)) { ASSERT(DVENCODERFORMAT_DVSD == dvFormat); ASSERT(DVENCODERRESOLUTION_720x480 == resolution); if ((DVENCODERVIDEOFORMAT_NTSC == videoFormat) (576 == m_vihDefault.bmiHeader.biHeight)) { // set the encoder to PAL if its NTSC videoFormat = DVENCODERVIDEOFORMAT_PAL; hr = pIDV- put_IFormatResolution(videoFormat, dvFormat, resolution, FALSE, NULL); } else if ((DVENCODERVIDEOFORMAT_PAL == videoFormat) (486 == m_vihDefault.bmiHeader.biHeight)) { // set the encoder to NTSC if its PAL videoFormat = DVENCODERVIDEOFORMAT_NTSC; hr = pIDV- put_IFormatResolution(videoFormat, dvFormat, resolution, FALSE, NULL); } } } if (SUCCEEDED(hr)) { // if the format is PAL, insert the Decklink field swap filter, PAL DV is the opposite // field order to PAL SD if (576 == m_vihDefault.bmiHeader.biHeight) { CComPtr IBaseFilter pPALFieldSwap = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_DecklinkFieldSwap, L"Decklink PAL Field Swap", pPALFieldSwap); if (SUCCEEDED(hr)) { // connect the smart-T capture pin to the PAL field swap filter hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, L"Capture", pPALFieldSwap, NULL); if (SUCCEEDED(hr)) { // connect the field swap filter to the DV encoder hr = CDSUtils ConnectFilters(m_pGraph, pPALFieldSwap, NULL, pDVEncoder, NULL); } } } else { // connect the smart-T capture pin to the DV Encoder hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, L"Capture", pDVEncoder, NULL); } if (SUCCEEDED(hr)) { // connect the DV encoder output to the AVI mux hr = CDSUtils ConnectFilters(m_pGraph, pDVEncoder, NULL, pAVIMux, NULL); if (SUCCEEDED(hr)) { // connect the mux to the file writer hr = CDSUtils ConnectFilters(m_pGraph, pAVIMux, NULL, pFileWriter, NULL); if (SUCCEEDED(hr)) { // video path connected now optionally connect the audio path if (FALSE == m_bAudioMute) { // connect the Decklink audio capture pin to the mux hr = CDSUtils ConnectFilters(m_pGraph, m_pAudioCapture, L"Capture", pAVIMux, NULL); } if (SUCCEEDED(hr)) { m_pControl- Run(); } } } } } } } } } } return hr; } //----------------------------------------------------------------------------- // CreateWMCaptureGraph // Create an optimum Windows Media capture graph HRESULT CDecklinkCaptureDlg CreateWMCaptureGraph() { HRESULT hr = S_OK; // locate the asf writer filter and add it to the graph CComPtr IBaseFilter pASFWriter = NULL; hr = CDSUtils AddFilter(m_pGraph, CLSID_WMAsfWriter, L"WM ASF Writer", pASFWriter); if (SUCCEEDED(hr)) { // set the output filename CComQIPtr IFileSinkFilter, IID_IFileSinkFilter pIFS = pASFWriter; if (pIFS) { USES_CONVERSION;// for T2W macro hr = pIFS- SetFileName(T2W(m_captureFile), NULL); if (SUCCEEDED(hr)) { hr = ConfigureWMEncoder(pASFWriter); } } if (SUCCEEDED(hr)) { if (FALSE == m_bAudioMute) { // connect the Decklink audio capture pin to the ASF writer hr = CDSUtils ConnectFilters(m_pGraph, m_pAudioCapture, pASFWriter, MEDIATYPE_Audio); } if (SUCCEEDED(hr)) { // connect the smart-T capture pin to the ASF writer hr = CDSUtils ConnectFilters(m_pGraph, m_pSmartT, pASFWriter, MEDIATYPE_Video); if (SUCCEEDED(hr)) { m_pControl- Run(); } } } } return hr; } //----------------------------------------------------------------------------- // ConfigureWMEncoder // Configure the Windows Media encoder HRESULT CDecklinkCaptureDlg ConfigureWMEncoder(IBaseFilter* pASFWriter) { HRESULT hr = S_OK; // modify the video output resolution of a system profile if (pASFWriter) { // simple system profile encoding CComQIPtr IConfigAsfWriter, IID_IConfigAsfWriter pICW = pASFWriter; if (pICW) { //NOTE You could just use the following for a default system profile //hr = pICW- ConfigureFilterUsingProfileGuid(WMProfile_XXX);// RE wmsysprf.h //NOTE If you want video only capture you must modify the profile to remove the audio // otherwise encoding will fail // Load a system profile and modify the resolution of the video output // NOTE The scope of the encoding is enormous, this just demonstrates how to change // the output video resolution from 320x240 to something larger. // Changing the resolution affects coding performance, it is likely that the encoder will // start to drop frames after a while. Using WM9 codecs will probably improve performance // and that has been left to the reader... ;o) // // get a profile manager CComPtr IWMProfileManager pIWMProfileManager = NULL; hr = WMCreateProfileManager( pIWMProfileManager); if (SUCCEEDED(hr)) { // load a system profile to modify CComPtr IWMProfile pIWMProfile = NULL; // NOTE Any WMProfile_XXX could be used here, or create a custom profile from scratch hr = pIWMProfileManager- LoadProfileByID(WMProfile_V80_FAIRVBRVideo, pIWMProfile); if (SUCCEEDED(hr)) { // search the streams for the video stream and attempt to modify the video size DWORD cbStreams = 0; hr = pIWMProfile- GetStreamCount( cbStreams); if (SUCCEEDED(hr)) { IWMStreamConfig* pIWMStreamConfig = NULL; GUID streamType = {0}; DWORD stream; if (m_bAudioMute) { // remove the audio stream for video only capture for (stream=0; stream cbStreams; ++stream) { hr = pIWMProfile- GetStream(stream, pIWMStreamConfig); if (SUCCEEDED(hr)) { hr = pIWMStreamConfig- GetStreamType( streamType); if (SUCCEEDED(hr)) { if (MEDIATYPE_Audio == streamType) { if (SUCCEEDED(pIWMProfile- RemoveStream(pIWMStreamConfig))) { --cbStreams; } SAFE_RELEASE(pIWMStreamConfig); break; } } } } } for (stream=0; stream cbStreams; ++stream) { hr = pIWMProfile- GetStream(stream, pIWMStreamConfig); if (SUCCEEDED(hr)) { hr = pIWMStreamConfig- GetStreamType( streamType); if (SUCCEEDED(hr) (MEDIATYPE_Video == streamType)) { // found the video stream CComQIPtr IWMMediaProps, IID_IWMMediaProps pIWMMediaProps = pIWMStreamConfig; if (pIWMMediaProps) { // get the size of the media type WM_MEDIA_TYPE* pMediaType = NULL; DWORD cbMediaType = 0; hr = pIWMMediaProps- GetMediaType(pMediaType, cbMediaType); if (SUCCEEDED(hr)) { pMediaType = (WM_MEDIA_TYPE*)new char [cbMediaType]; if (pMediaType) { hr = pIWMMediaProps- GetMediaType(pMediaType, cbMediaType); if (SUCCEEDED(hr)) { BITMAPINFOHEADER* pbmih = NULL; if (WMFORMAT_VideoInfo == pMediaType- formattype) { WMVIDEOINFOHEADER* pvih = (WMVIDEOINFOHEADER*)pMediaType- pbFormat; pbmih = pvih- bmiHeader; } else if (WMFORMAT_MPEG2Video == pMediaType- formattype) { WMVIDEOINFOHEADER2* pvih = (WMVIDEOINFOHEADER2*) ((WMMPEG2VIDEOINFO*)pMediaType- pbFormat)- hdr; pbmih = pvih- bmiHeader; } if (pbmih) { // modify the video dimensions, set the property, reconfigure the stream // and then configure the ASF writer with this modified profile pbmih- biWidth = 640;// was 320; pbmih- biHeight = 480;// was 240; pbmih- biSizeImage = pbmih- biWidth * pbmih- biHeight * pbmih- biBitCount / 8;// NOTE This calculation is not correct for all bit depths hr = pIWMMediaProps- SetMediaType(pMediaType); if (SUCCEEDED(hr)) { // config the ASF writer filter to use this modified system profile hr = pIWMProfile- ReconfigStream(pIWMStreamConfig); if (SUCCEEDED(hr)) { hr = pICW- ConfigureFilterUsingProfile(pIWMProfile); } } } } delete [] (char*)pMediaType; } } } } SAFE_RELEASE(pIWMStreamConfig); } } } } } /* // modify other ASF writer properties IServiceProvider* pProvider = NULL; hr = pASFWriter- QueryInterface(IID_IServiceProvider, reinterpret_cast void** ( pProvider)); if (SUCCEEDED(hr)) { IID_IWMWriterAdvanced2* pWMWA2 = NULL; hr = pProvider- QueryService(IID_IID_IWMWriterAdvanced2, IID_IID_IWMWriterAdvanced2, reinterpret_cast void** ( pWMWA2)); if (SUCCEEDED(hr)) { // set the deinterlace mode pWMWA2- GetInputSetting(...); SAFE_RELEASE(pWMWA2); } SAFE_RELEASE(pProvider); } */ } } else { hr = E_INVALIDARG; } return hr; } //----------------------------------------------------------------------------- // DestroyGraph // Remove all intermediate filters, keep any Decklink and video render filters as // these are used by all the graphs. HRESULT CDecklinkCaptureDlg DestroyGraph() { HRESULT hr = S_OK; if (m_pGraph m_pControl) { m_pControl- Stop(); // release our outstanding reference on this filter so it can be removed from the graph SAFE_RELEASE(m_pSmartT); // retrieve the name of the capture device, don t remove it in this method PWSTR pNameVideoCapture = (PWSTR)m_videoDeviceCtrl.GetItemData(m_videoDeviceCtrl.GetCurSel()); PWSTR pNameAudioCapture = (PWSTR)m_audioDeviceCtrl.GetItemData(m_audioDeviceCtrl.GetCurSel()); CComPtr IEnumFilters pEnum = NULL; hr = m_pGraph- EnumFilters( pEnum); if (SUCCEEDED(hr)) { IBaseFilter* pFilter = NULL; while (S_OK == pEnum- Next(1, pFilter, NULL)) { FILTER_INFO filterInfo = {0}; hr = pFilter- QueryFilterInfo( filterInfo); if (SUCCEEDED(hr)) { SAFE_RELEASE(filterInfo.pGraph); if ((NULL == wcsstr(filterInfo.achName, pNameVideoCapture)) (NULL == wcsstr(filterInfo.achName, pNameAudioCapture)) (NULL == wcsstr(filterInfo.achName, L"Video Renderer"))) { hr = m_pGraph- RemoveFilter(pFilter); if (SUCCEEDED(hr)) { hr = pEnum- Reset(); } } } SAFE_RELEASE(pFilter); } } } else { hr = E_POINTER; } return hr; } //----------------------------------------------------------------------------- // InitialiseVideoPreview // In short get the video screen renderer to draw into the picture control, which is our preview window // the following code sets this up, in addition to adding the HandleGraphEvent and WindowProc methods // read the DXSDK docos for more detailed information void CDecklinkCaptureDlg InitialiseVideoPreview(void) { // modify the preview window if (m_pVideoRenderer) { if (NULL == m_pIVW) { if (SUCCEEDED(m_pVideoRenderer- QueryInterface(IID_IVideoWindow, reinterpret_cast void** ( m_pIVW)))) { // get the window to handle redraws, etc // Set msg drain of VideoWindow to point to our dialog window. The dialog s // window procedure then handles events from the VideoWindow. HRESULT hr = m_pIVW- put_MessageDrain(reinterpret_cast OAHWND (m_hWnd)); if (NULL == m_pMediaEvent) { // Make graph send WM_GRAPHNOTIFY when it wants our attention see "Learning // When an Event Occurs" in the DX9 documentation. hr = m_pGraph- QueryInterface(IID_IMediaEventEx, reinterpret_cast void** ( m_pMediaEvent)); if (SUCCEEDED(hr)) { hr = m_pMediaEvent- SetNotifyWindow(reinterpret_cast OAHWND (m_hWnd), WM_GRAPHNOTIFY, 0); } // object created for it. RECT rc; m_preview.GetClientRect( rc); m_pIVW- SetWindowPosition(rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top); // VideoWindow is a child window of the bounding rect hr = m_pIVW- put_WindowStyle(WS_CHILD); hr = m_pIVW- put_Owner(reinterpret_cast OAHWND (m_preview.GetSafeHwnd())); hr = m_pIVW- SetWindowForeground(-1); } } } } } //----------------------------------------------------------------------------- // PopulateDeviceControl // Fill device combo box with available devices of the specified category HRESULT CDecklinkCaptureDlg PopulateDeviceControl(const GUID* pCategory, CComboBox* pCtrl) { HRESULT hr = S_OK; if (pCategory pCtrl) { // first enumerate the system devices for the specifed class and filter name CComPtr ICreateDevEnum pSysDevEnum = NULL; hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, reinterpret_cast void** ( pSysDevEnum)); if (SUCCEEDED(hr)) { CComPtr IEnumMoniker pEnumCat = NULL; hr = pSysDevEnum- CreateClassEnumerator(*pCategory, pEnumCat, 0); if (S_OK == hr) { IMoniker* pMoniker = NULL; bool Loop = true; while ((S_OK == pEnumCat- Next(1, pMoniker, NULL)) Loop) { IPropertyBag* pPropBag = NULL; hr = pMoniker- BindToStorage(0, 0, IID_IPropertyBag, reinterpret_cast void** ( pPropBag)); if (SUCCEEDED(hr)) { VARIANT varName; VariantInit( varName); hr = pPropBag- Read(L"FriendlyName", varName, 0); if (SUCCEEDED(hr)) { size_t len = wcslen(varName.bstrVal) + 1; PWSTR pName = new WCHAR [len]; StringCchCopyW(pName, len, varName.bstrVal); CW2AEX buf(varName.bstrVal); pCtrl- SetItemData(pCtrl- AddString(buf), (DWORD)pName); } VariantClear( varName); // contained within a loop, decrement the reference count SAFE_RELEASE(pPropBag); } SAFE_RELEASE(pMoniker); } } } } else { hr = E_POINTER; } return hr; } //----------------------------------------------------------------------------- // PopulateVideoControl // Fill video format combo box with supported video formats using the IAMStreamConfig // interface. HRESULT CDecklinkCaptureDlg PopulateVideoControl() { HRESULT hr = S_OK; if (m_pVideoCapture) { // free mediatypes attached to format controls int count = m_videoFormatCtrl.GetCount(); if (count) { for (int item=0; item count; ++item) { DeleteMediaType((AM_MEDIA_TYPE*)m_videoFormatCtrl.GetItemData(item)); } m_videoFormatCtrl.ResetContent(); } // locate the video capture pin and QI for stream control CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pVideoCapture, MEDIATYPE_Video, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // loop through all the capabilities (video formats) and populate the control int count, size; hr = pISC- GetNumberOfCapabilities( count, size); if (SUCCEEDED(hr)) { if (sizeof(VIDEO_STREAM_CONFIG_CAPS) == size) { AM_MEDIA_TYPE* pmt = NULL; VIDEO_STREAM_CONFIG_CAPS vscc; VIDEOINFOHEADER* pvih = NULL; for (int index=0; index count; ++index) { hr = pISC- GetStreamCaps(index, pmt, reinterpret_cast BYTE* ( vscc)); if (SUCCEEDED(hr)) { char buffer[128]; WORD PixelFormat; float FrameRate; ZeroMemory(buffer, sizeof(buffer)); pvih = (VIDEOINFOHEADER*)pmt- pbFormat; char* pPixelFormatLUT[] = {"4 2 2", "4 4 4"}; if (pvih- bmiHeader.biBitCount == 16) PixelFormat = 8; else if (pvih- bmiHeader.biBitCount == 20) PixelFormat = 10; else PixelFormat = pvih- bmiHeader.biBitCount; // provide a useful description of the formats if (486 == pvih- bmiHeader.biHeight) { if (417083 == pvih- AvgTimePerFrame) { StringCbPrintfA(buffer, sizeof(buffer), "NTSC %d-bit %s (3 2 pulldown removal)", PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { StringCbPrintfA(buffer, sizeof(buffer), "NTSC %d-bit %s", PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } } else if (576 == pvih- bmiHeader.biHeight) { StringCbPrintfA(buffer, sizeof(buffer), "PAL %d-bit %s", PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { char* pFrameRateFormat[] = {"%.2f", "%.0f"}; FrameRate = (float)(long)UNITS / pvih- AvgTimePerFrame; if ((720 == pvih- bmiHeader.biHeight) (59.94 FrameRate)) { if ((FrameRate - (int)FrameRate) 0.01) { StringCbPrintfA(buffer, sizeof(buffer), "HD720 %.2fp %d-bit %s (Overcranked 60p)", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { StringCbPrintfA(buffer, sizeof(buffer), "HD720 %.0fp %d-bit %s (Overcranked 60p)", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } } else if ((720 == pvih- bmiHeader.biHeight) (59.94 = FrameRate)) { if ((FrameRate - (int)FrameRate) 0.01) { StringCbPrintfA(buffer, sizeof(buffer), "HD720 %.2fp %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { StringCbPrintfA(buffer, sizeof(buffer), "HD720 %.0fp %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } } else if ((1080 == pvih- bmiHeader.biHeight) (50.00 = FrameRate)) { if ((FrameRate - (int)FrameRate) 0.01) { StringCbPrintfA(buffer, sizeof(buffer), "HD1080 %.2fi %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { StringCbPrintfA(buffer, sizeof(buffer), "HD1080 %.0fi %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } } else { if ((FrameRate - (int)FrameRate) 0.01) { StringCbPrintfA(buffer, sizeof(buffer), "HD1080 %.2fPsF %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } else { StringCbPrintfA(buffer, sizeof(buffer), "HD1080 %.0fPsF %d-bit %s", FrameRate, PixelFormat, pPixelFormatLUT[(30 == PixelFormat)]); } } } // add the item description to combo box int n = m_videoFormatCtrl.AddString(buffer); // store media type pointer in item s data section m_videoFormatCtrl.SetItemData(n, (DWORD_PTR)pmt); // set default format if ((pvih- AvgTimePerFrame == m_vihDefault.AvgTimePerFrame) (pvih- bmiHeader.biWidth == m_vihDefault.bmiHeader.biWidth) (pvih- bmiHeader.biHeight == m_vihDefault.bmiHeader.biHeight) (pvih- bmiHeader.biBitCount == m_vihDefault.bmiHeader.biBitCount)) { m_videoFormatCtrl.SetCurSel(n); pISC- SetFormat(pmt); } } } } else { m_videoFormatCtrl.AddString("ERROR Unable to retrieve video formats"); } } } } else { hr = E_POINTER; } return hr; } //----------------------------------------------------------------------------- // PopulateAudioControl // Fill audio format combo box with supported audio formats using the IAMStreamConfig // interface. HRESULT CDecklinkCaptureDlg PopulateAudioControl() { HRESULT hr = S_OK; if (m_pAudioCapture) { // free mediatypes attached to format controls int count = m_audioFormatCtrl.GetCount(); if (count) { for (int item=0; item count; ++item) { DeleteMediaType((AM_MEDIA_TYPE*)m_audioFormatCtrl.GetItemData(item)); } m_audioFormatCtrl.ResetContent(); } // locate the audio capture pin and QI for stream control CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pAudioCapture, MEDIATYPE_Audio, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // loop through all the capabilities (audio formats) and populate the control int count, size; hr = pISC- GetNumberOfCapabilities( count, size); if (SUCCEEDED(hr)) { if (sizeof(AUDIO_STREAM_CONFIG_CAPS) == size) { AM_MEDIA_TYPE* pmt = NULL; AUDIO_STREAM_CONFIG_CAPS ascc; WAVEFORMATEX* pwfex = NULL; for (int index=0; index count; ++index) { hr = pISC- GetStreamCaps(index, pmt, reinterpret_cast BYTE* ( ascc)); if (SUCCEEDED(hr)) { char buffer[32]; ZeroMemory(buffer, sizeof(buffer)); pwfex = (WAVEFORMATEX*)pmt- pbFormat; // provide a useful description of the formats if (1 == pwfex- nChannels) { StringCbPrintfA(buffer, sizeof(buffer), "%d channel, %2.1fkHz, %d-bit", (int)pwfex- nChannels, (float)pwfex- nSamplesPerSec / 1000, (int)pwfex- wBitsPerSample); } else { StringCbPrintfA(buffer, sizeof(buffer), "%d channels, %2.1fkHz, %d-bit", (int)pwfex- nChannels, (float)pwfex- nSamplesPerSec / 1000, (int)pwfex- wBitsPerSample); } // add the item description to combo box int n = m_audioFormatCtrl.AddString(buffer); // store media type pointer in item s data section m_audioFormatCtrl.SetItemData(n, (DWORD_PTR)pmt); // set default format if ((pwfex- wFormatTag == m_wfexDefault.wFormatTag) (pwfex- nChannels == m_wfexDefault.nChannels) (pwfex- nSamplesPerSec == m_wfexDefault.nSamplesPerSec) (pwfex- nAvgBytesPerSec == m_wfexDefault.nAvgBytesPerSec)) { m_audioFormatCtrl.SetCurSel(n); pISC- SetFormat(pmt); } } } } else { m_audioFormatCtrl.AddString("ERROR Unable to retrieve audio formats"); } } } } else { hr = E_POINTER; } return hr; } //----------------------------------------------------------------------------- // PopulateCompressionControl // Fill compression control with a selection of video compressors, locate the // encoders and add them to the combo box if they exist. HRESULT CDecklinkCaptureDlg PopulateCompressionControl() { int n = m_compressionCtrl.AddString("Uncompressed"); m_compressionCtrl.SetItemData(n, (DWORD_PTR)ENC_NONE); // search for the DV encoder, MPEG encoder and WM encoder IBaseFilter* pFilter = NULL; HRESULT hr = CoCreateInstance(CLSID_DVVideoEnc, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast void** ( pFilter)); if (SUCCEEDED(hr)) { n = m_compressionCtrl.SetCurSel(m_compressionCtrl.AddString("DV Video Encoder")); m_compressionCtrl.SetItemData(n, (DWORD_PTR)ENC_DV); SAFE_RELEASE(pFilter); } hr = CoCreateInstance(CLSID_WMAsfWriter, 0, CLSCTX_INPROC_SERVER, IID_IBaseFilter, reinterpret_cast void** ( pFilter)); if (SUCCEEDED(hr)) { n = m_compressionCtrl.SetCurSel(m_compressionCtrl.AddString("Windows Media Encoder")); m_compressionCtrl.SetItemData(n, (DWORD_PTR)ENC_WM); SAFE_RELEASE(pFilter); } m_compressionCtrl.SetCurSel(m_compressor); return S_OK; } //----------------------------------------------------------------------------- // OnCbnSelchangeComboVideodevice // Rebuild graph with selected capture device void CDecklinkCaptureDlg OnCbnSelchangeComboVideodevice() { SAFE_RELEASE(m_pVideoCapture);// release our outstanding reference // remove intermediate filters, since the device selection has changed the capture device will also be removed HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { // rebuild graph with new capture device selection PWSTR pName = (PWSTR)m_videoDeviceCtrl.GetItemData(m_videoDeviceCtrl.GetCurSel()); if (pName) { hr = CDSUtils AddFilter2(m_pGraph, CLSID_VideoInputDeviceCategory, pName, m_pVideoCapture); if (SUCCEEDED(hr)) { // as the device has changed get the current operating format so that the control // and display this as the current selection CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pVideoCapture, MEDIATYPE_Video, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // get the current format of the device to set the current selection of the control AM_MEDIA_TYPE* pamt = NULL; hr = pISC- GetFormat( pamt); if (SUCCEEDED(hr)) { if (pamt- pbFormat) { m_vihDefault = *(VIDEOINFOHEADER*)pamt- pbFormat; } DeleteMediaType(pamt); } } hr = PopulateVideoControl();// repopulate the control with formats from the new device if (SUCCEEDED(hr)) { hr = CreatePreviewGraph();// rebuild the graph with the new device } } } else { hr = E_POINTER; } } } //----------------------------------------------------------------------------- // OnCbnSelchangeComboAudiodevice // Rebuild graph with selected capture device void CDecklinkCaptureDlg OnCbnSelchangeComboAudiodevice() { SAFE_RELEASE(m_pAudioCapture);// release our outstanding reference // remove intermediate filters, since the device selection has changed the capture device will also be removed HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { PWSTR pName = (PWSTR)m_audioDeviceCtrl.GetItemData(m_audioDeviceCtrl.GetCurSel()); if (pName) { hr = CDSUtils AddFilter2(m_pGraph, CLSID_AudioInputDeviceCategory, pName, m_pAudioCapture); if (SUCCEEDED(hr)) { // as the device has changed get the current operating format so that the control // and display this as the current selection CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pAudioCapture, MEDIATYPE_Audio, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // get the current format of the device to set the current selection of the control AM_MEDIA_TYPE* pamt = NULL; hr = pISC- GetFormat( pamt); if (SUCCEEDED(hr)) { if (pamt- pbFormat) { m_wfexDefault = *(WAVEFORMATEX*)pamt- pbFormat; } DeleteMediaType(pamt); } } hr = PopulateAudioControl();// repopulate the control with formats from the new device if (SUCCEEDED(hr)) { hr = CreatePreviewGraph();// rebuild the graph with the new device } } } else { hr = E_POINTER; } } } //----------------------------------------------------------------------------- // OnCbnSelchangeComboVideoformats // Rebuild preview graph if format selection changed void CDecklinkCaptureDlg OnCbnSelchangeComboVideoformats() { HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { // locate the video capture pin and QI for stream control CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pVideoCapture, MEDIATYPE_Video, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // set the new media format AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)m_videoFormatCtrl.GetItemData(m_videoFormatCtrl.GetCurSel()); m_vihDefault = *(VIDEOINFOHEADER*)pmt- pbFormat; ASSERT(sizeof(VIDEOINFOHEADER) = pmt- cbFormat); hr = pISC- SetFormat(pmt); if (SUCCEEDED(hr)) { // save the new format EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("VideoFormat", reinterpret_cast const BYTE* ( m_vihDefault), sizeof(m_vihDefault))); // update compression control, we don t have an HD compression filter so disable compression for HD formats if (576 m_vihDefault.bmiHeader.biHeight) { m_compressor = 0; m_compressionCtrl.SetCurSel(m_compressor); // save the new state EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("VideoCompressor", reinterpret_cast const BYTE* ( m_compressor), sizeof(m_compressor))); m_bEnableCompressionCtrl = FALSE; } else { m_bEnableCompressionCtrl = TRUE; } EnableControls(); // rebuild the graph hr = CreatePreviewGraph(); } } } } //----------------------------------------------------------------------------- // OnCbnSelchangeComboAudioformats // Rebuild preview graph if format selection changed void CDecklinkCaptureDlg OnCbnSelchangeComboAudioformats() { HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { // locate the audio capture pin and QI for stream control CComPtr IAMStreamConfig pISC = NULL; hr = CDSUtils FindPinInterface(m_pAudioCapture, MEDIATYPE_Audio, PINDIR_OUTPUT, IID_IAMStreamConfig, reinterpret_cast void** ( pISC)); if (SUCCEEDED(hr)) { // set the new media format AM_MEDIA_TYPE* pmt = (AM_MEDIA_TYPE*)m_audioFormatCtrl.GetItemData(m_audioFormatCtrl.GetCurSel()); m_wfexDefault = *(WAVEFORMATEX*)pmt- pbFormat; ASSERT(sizeof(WAVEFORMATEX) == pmt- cbFormat); hr = pISC- SetFormat(pmt); if (SUCCEEDED(hr)) { // save the new format EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("AudioFormat", reinterpret_cast const BYTE* ( m_wfexDefault), sizeof(m_wfexDefault))); // rebuild the graph hr = CreatePreviewGraph(); } } } } //----------------------------------------------------------------------------- // OnCbnSelchangeComboCompression // Rebuild preview graph if compression selection changed void CDecklinkCaptureDlg OnCbnSelchangeComboCompression() { HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { // save the new state m_compressor = m_compressionCtrl.GetCurSel(); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("VideoCompressor", reinterpret_cast const BYTE* ( m_compressor), sizeof(m_compressor))); // rebuild the graph hr = CreatePreviewGraph(); } } //----------------------------------------------------------------------------- // OnBnClickedCheckAudiomute // Rebuild the capture graph to reflect the new audio setting void CDecklinkCaptureDlg OnBnClickedCheckAudiomute() { CButton* pCheck = (CButton*)GetDlgItem(IDC_CHECK_AUDIOMUTE); if (pCheck) { m_bAudioMute = pCheck- GetState() 0x0003; HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { // save the new state EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("AudioMute", reinterpret_cast const BYTE* ( m_bAudioMute), sizeof(m_bAudioMute))); // rebuild the graph which reflects the new audio setting hr = CreatePreviewGraph(); } } } //----------------------------------------------------------------------------- // OnBnClickedButtonBrowse // Create a file open dialog to browse for a file location void CDecklinkCaptureDlg OnBnClickedButtonBrowse() { char BASED_CODE szFilters[] = "Windows Media Files|*.avi;*.asf;*.wmv|All Files (*.*)|*.*||"; char* pExt[] = {"*.avi", "*.avi", "*.asf;*.wmv"}; CFileDialog FileDlg(TRUE, "Windows Media Files", pExt[m_compressor], 0, szFilters, this); if (FileDlg.DoModal() == IDOK) { m_captureFile = FileDlg.GetPathName(); m_captureFileCtrl.SetWindowText(m_captureFile); } } //----------------------------------------------------------------------------- // OnBnClickedButtonCapture // Create a capture graph a start capture void CDecklinkCaptureDlg OnBnClickedButtonCapture() { HRESULT hr = CreateCaptureGraph(); if (SUCCEEDED(hr)) { if (m_pControl) { hr = m_pControl- Run(); if (SUCCEEDED(hr)) { DisableControls(); } } } } //----------------------------------------------------------------------------- // OnBnClickedButtonStop // Stop capture and revert to preview void CDecklinkCaptureDlg OnBnClickedButtonStop() { HRESULT hr = DestroyGraph(); if (SUCCEEDED(hr)) { hr = CreatePreviewGraph(); if (SUCCEEDED(hr)) { EnableControls(); } } } //----------------------------------------------------------------------------- // EnableControls // void CDecklinkCaptureDlg EnableControls(void) { CWnd* pWnd = GetDlgItem(IDC_COMBO_VIDEOFORMATS); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_COMBO_AUDIOFORMATS); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_CHECK_AUDIOMUTE); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_COMBO_COMPRESSION); m_bEnableCompressionCtrl = (576 m_vihDefault.bmiHeader.biHeight) ? FALSE TRUE;// don t have an HDV codec do disable compression control for HD formats pWnd- EnableWindow(m_bEnableCompressionCtrl); pWnd = GetDlgItem(IDC_EDIT_CAPTUREFILE); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_BUTTON_BROWSE); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_BUTTON_CAPTURE); pWnd- EnableWindow(TRUE); pWnd = GetDlgItem(IDC_BUTTON_STOP); pWnd- EnableWindow(FALSE); } //----------------------------------------------------------------------------- // DisableControls // void CDecklinkCaptureDlg DisableControls(void) { CWnd* pWnd = GetDlgItem(IDC_COMBO_VIDEOFORMATS); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_COMBO_AUDIOFORMATS); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_CHECK_AUDIOMUTE); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_COMBO_COMPRESSION); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_EDIT_CAPTUREFILE); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_BUTTON_BROWSE); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_BUTTON_CAPTURE); pWnd- EnableWindow(FALSE); pWnd = GetDlgItem(IDC_BUTTON_STOP); pWnd- EnableWindow(TRUE); } //----------------------------------------------------------------------------- // QueryRegistry // retrieve previous media formats from registry void CDecklinkCaptureDlg QueryRegistry(void) { if (ERROR_SUCCESS == m_regUtils.Open("DecklinkCaptureSample")) { EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.GetBinary("VideoFormat", reinterpret_cast LPBYTE ( m_vihDefault), sizeof(m_vihDefault))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.GetBinary("AudioFormat", reinterpret_cast LPBYTE ( m_wfexDefault), sizeof(m_wfexDefault))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.GetBinary("AudioMute", reinterpret_cast LPBYTE ( m_bAudioMute), sizeof(m_bAudioMute))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.GetBinary("VideoCompressor", reinterpret_cast LPBYTE ( m_compressor), sizeof(m_compressor))); WCHAR captureFile[MAX_PATH]; ZeroMemory(captureFile, sizeof(captureFile)); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.GetString("CaptureFile", reinterpret_cast LPBYTE (captureFile), sizeof(captureFile))); m_captureFile = captureFile; } else { // create the key and registry values if (ERROR_SUCCESS == m_regUtils.Create("DecklinkCaptureSample")) { EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("VideoFormat", reinterpret_cast const BYTE* ( m_vihDefault), sizeof(m_vihDefault))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("AudioFormat", reinterpret_cast const BYTE* ( m_wfexDefault), sizeof(m_wfexDefault))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("AudioMute", reinterpret_cast const BYTE* ( m_bAudioMute), sizeof(m_bAudioMute))); EXECUTE_ASSERT(ERROR_SUCCESS == m_regUtils.SetBinary("VideoCompressor", reinterpret_cast const BYTE* ( m_compressor), sizeof(m_compressor))); } } // update mute audio check box control CButton* pButton = (CButton*)GetDlgItem(IDC_CHECK_AUDIOMUTE); pButton- SetCheck(m_bAudioMute); }
https://w.atwiki.jp/suffix/pages/15.html
Cygwin+Opencv VC+++Opencv
https://w.atwiki.jp/darui_program/pages/236.html
#include "gtunit.h" GT_TEST_FUNC(TEST1, Test1) { new int; // メモリリーク } class Foo public GT_FORM { protected int m_num; public Foo() m_num( 0 ) { } void Print() { std cout m_num std endl; } }; GT_TEST_CLASS(Foo, Print) { m_num = 100; Print(); } GT_TEST_CLASS(Foo, NumEqual) { ASSERT_EQ( 0, m_num ); ASSERT_NE( 1, m_num ); } /* Running main() from gtest_main.cc [==========] Running 3 tests from 2 test cases. [----------] Global test environment set-up. [----------] 1 test from TEST1 [ RUN ] TEST1.Test1 d \programming\googletest\main.cpp(3) error Value of alloc.Check() Actual false Expected true MEMORY_LEAK!! FILE d \programming\googletest\main.cpp LINE 5 [ FAILED ] TEST1.Test1 [----------] 2 tests from Foo [ RUN ] Foo.Print 100 [ OK ] Foo.Print [ RUN ] Foo.NumEqual [ OK ] Foo.NumEqual [----------] Global test environment tear-down [==========] 3 tests from 2 test cases ran. [ PASSED ] 2 tests. [ FAILED ] 1 test, listed below [ FAILED ] TEST1.Test1 1 FAILED TEST 続行するには何かキーを押してください . . . */
https://w.atwiki.jp/chugoku/pages/56.html
http //mergedoc.sourceforge.jp/からC/C++のパッケージをダウンロード 解凍するとeclipseやmingwなどのフォルダができるのでこのフォルダをそのままC \に移動。 フォルダ名がpleiades-e3.5-cpp-jre_20090930とゴチャゴチャになっているがとりあえずそのままで。。 C \pleiades-e3.5-cpp-jre_20090930\eclipse\eclispe.exeのショートカットキーをメニューに追加してすぐに起動できるようにしておこう。 これで動くのだ。 これで動くということは、コントロールパネルのプログラムの追加・削除とは関係ない。uninstallとはC \pleiades-e3.5-cpp-jre_20090930のフォルダを消せばよい。 1、とりあえずhello world eclipseを起動したらファイルー新規プロジェクトC++を選んで以下の設定 imageプラグインエラー ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (helloc++.gif) C/C++コンパイラはmingwを使う。世界的に超有名Windows用GNUコンパイラgccだ。 実行すると下の方に「!!!Hello World!!!」が見える。DOSっぽいコンソールを開いてないのでわかりにくいがコンパイル後に実行できている。 C \pleiades-e3.5-cpp-jre_20090930\workspace\helloc++\Debugにexeファイルがあるはずだ。 2、OpenCVのライブラリも使えるようにする C/C++のコンパイルで特別なライブラリを使う時(特別でもなくよくあることだが)、ヘッダファイル(テキストファイル)とライブラリ(バイナリファイル)の設定が必要だ。 OpenCV1.0の場合は、ヘッダファイルの位置は以下。 C \Program Files\OpenCV\cv\include C \Program Files\OpenCV\cvaux\include C \Program Files\OpenCV\cxcore\include C \Program Files\OpenCV\otherlibs\highgui ライブラリファイル。具体的には*.libファイルのパスの指定は以下。 C \Program Files\OpenCV\lib プロジェクトのプロパティを開く imageプラグインエラー ご指定のファイルが見つかりません。ファイル名を確認して、再度指定してください。 (プロジェクトのプロパティ.gif) CとC++の両方に設定する必要があるのですべての言語にしておくとちょっと楽? アセンブリ。。。には必要ないので後で削除しよう。 以下はライブラリのパスの設定 さらに、リンカーにライブラリファイル名を教える。(C言語でmathをおしえるやつ) んん。面倒。 以下にプロジェクト下にできる.cprojectファイルを置いておく。 .cproject 新規にプロジェクトを作ったらこのファイルをそのプロジェクト下のフォルダに上書きしよう。 cprojectファイル名の先頭の「.」を忘れずに!! 例、ttというC++のプロジェクトを作りると以下のフォルダttができる。 C \pleiades-e3.5-cpp-jre_20090930\workspace\tt ここに.cprojectファイルを上書きするのだ。 さらに、配布した.cprojectのプロジェクト名は「lllll」(l5つ)という名前にしている。 だからこの部分を全部置換しないといけない。「lllll」を「tt」に置換する。 このファイルを呼び込ませるにはeclipseを再起動する。(この方法しかわからん) これで上記のinclude、lib、lib名の設定など全部できてるはず。 何がうれしい いいことあるの? eclipseの統合開発環境は、includeしたファイルを呼び込み、関数名やincludeファイルを書くときに入力を補完してくれる。 少し先頭を入力したらctrl+spaceをおす。 (何も入れなくてもctrl+spaceをおす)
https://w.atwiki.jp/alabama_country/pages/32.html
基数ソート テンプレートやべえ 解決したので簡単にまとめます。 template class T class radixsort_list { public //略 friend std ostream operator (std ostream stream, radixsort_list T obj) { //エラー出る。 for(std vector std deque T iterator i = obj.data.begin(); i != obj.data.end(); ++i) for(std deque T iterator j = i- begin(); j != i- end(); ++j) stream *j std endl; return stream; }; //略 }; と書くと radixsort_byte.cpp In function ‘std ostream operator (std ostream , radixsort_list T )’ radixsort_byte.cpp 18 error expected `; before ‘i’ radixsort_byte.cpp 19 error ‘i’ was not declared in this scope radixsort_byte.cpp 20 error expected `; before ‘j’ radixsort_byte.cpp 21 error ‘j’ was not declared in this scope radixsort_byte.cpp In function ‘std ostream operator (std ostream , radixsort_list unsigned int )’ radixsort_byte.cpp 66 instantiated from here radixsort_byte.cpp 18 error dependent-name ‘std vector iterator’ is parsed as a non-type, but instantiation yields a type radixsort_byte.cpp 18 note say ‘typename std vector iterator’ if a type is meant radixsort_byte.cpp 20 error dependent-name ‘std deque iterator’ is parsed as a non-type, but instantiation yields a type radixsort_byte.cpp 20 note say ‘typename std deque iterator’ if a type is meant このようなエラーが吐かれる。 救いの光が! @yuyarinに投げたところ解答をいただいたので記す。 typename エラー嫁 エラーをよく見ると say ‘typename std deque iterator’ if a type is meant とある。つまり、typenameとしていすれば型名であることが示されるということ。結局答えは自明ということでしたorz.ちなみに実際にはtypename使えとアドバイスをくださいました。 構造 STLのソートのようにイテレータ関数として実装せよとのことなので書き直した。 ソース radixsort.h #include iterator #include vector #include deque struct EXCEPT_SORT_OVERFLOW { } EXCEPT_SORT_OVERFLOW_; template class Iterator void radixsort(Iterator begin, Iterator end) { typedef typename std iterator_traits Iterator value_type T; // data std vector std deque T data, temp; // bit operation const int SEG = 8; const int WIDTH = sizeof(T) * 8 / SEG; T mask = (T)~(~0x0 SEG); //read sort data.resize(0x1 SEG); for(Iterator i=begin; i != end; ++i) data[*i mask].push_back(*i); mask = SEG; for(int loop = 1; loop WIDTH; mask = SEG, ++loop) { temp.resize(0x1 SEG); for(typename std vector std deque T iterator i = data.begin(); i != data.end(); ++i) for(typename std deque T iterator j = i- begin(); j != i- end(); ++j) temp[(*j mask) (SEG * loop)].push_back(*j); swap(data, temp); temp.clear(); } //write Iterator target = begin; for(typename std vector std deque T iterator i = data.begin(); i != data.end(); ++i) for(typename std deque T iterator j = i- begin(); j != i- end(); ++j) { if(target == end) throw EXCEPT_SORT_OVERFLOW_; *target = *j, ++target; } } wrapper.cpp #include iostream #include vector #include cstdlib #include ctime #include "radixsort.h" #define LENGTH(x) (sizeof(x)/sizeof((x)[0])) template class T class wrapper_vector { public void input(T *arr, int arr_length); friend std ostream operator (std ostream stream, wrapper_vector T obj) { for(typename std vector T iterator j = obj.data.begin(); j != obj.data.end(); ++j) stream *j " , "; stream std endl; return stream; }; private std vector T data; //const static int SEG = 8; }; template class T void wrapper_vector T input(T *arr, int arr_length) { data.resize(arr_length); for(int i=0; i arr_length; ++i) data[i] = arr[i]; try { radixsort(data.begin(), data.end()); } catch(EXCEPT_SORT_OVERFLOW) { std cerr "なぜか数が合いません" std endl; } } int main() { //unsigned int array[] = {31,41,59,26,53,58,97,93,23,84,62,64,33,83,27,95,02,88}; unsigned seed(time(NULL)); srand(seed); std cerr "seed " seed std endl; unsigned long array[1000]; for(int i=0; i (int)LENGTH(array); ++i) array[i] = (unsigned long)rand(); wrapper_vector unsigned long *pSort; pSort = new wrapper_vector unsigned long ; pSort- input(array, LENGTH(array)); std cout *pSort; delete pSort; char str[] = "The quick brown fox jumps over a lazy dog."; wrapper_vector char *pSort2; pSort2 = new wrapper_vector char ; pSort2- input(str, LENGTH(str)); std cout *pSort2; delete pSort2; }
https://w.atwiki.jp/suffix/pages/17.html
画像の縦横 ←javaのイメージクラスの話から転載。 画像にpixel単位でアクセスする方法 アフィン変換・透視変換 クロマキー処理 テンプレートマッチングを行う 射影変換行列 表色系変換 輪郭抽出 マウス処理 色領域抽出 ラベリング SIFTとかSURFとか Gabor特徴とか ノイズ除去とか円滑化とか IPL_DEPTH_8Uってサンプルで良く見るけど、これって何? デバッグ系 opencvリファレンスマニュアル http //opencv.jp/opencv-1.1.0/document/index.html opencvデバッグ日記 http //www19.atwiki.jp/kanelab/pages/13.html Opencv@Chihara-Lab. http //chihara.naist.jp/opencv/?FrontPage